【发布时间】:2012-03-09 13:25:24
【问题描述】:
我正在尝试创建一个简单的函数计时器/分析器。我的主要目标是创建一个函数,我可以快速、轻松、不显眼地添加到我想要分析的任何函数调用中。
例如分析foo、bar和baz我想要一个ft(函数计时器)函数,它可以执行以下操作,尽可能少地影响原始代码:
ft(foo());
ft(bar(1, 2, 3));
int result = ft(baz());
string result = ft(qux("a", 2, 3.4));
注意,在baz 和qux 的情况下,ft 返回的结果应该是函数本身返回的结果。
ft 处理所有的计时和日志记录等。
我遇到过几个线程,它们提到了如何为具有任意参数的函数执行函数回调,但没有那么多甚至提到如何处理返回值。
这是最接近的:Variable number of arguments (va_list) with a function callback?,但我在尝试处理 void 函数以及返回值的函数时陷入困境。
我开始认为使用宏是实现此目的的方法,但也许有更好的方法。
这是我目前微弱的尝试(删节):
static Timer fTimer;
class VoidFuncBase
{
public:
virtual void operator()() = 0;
};
class VoidFuncWrapper0 : public VoidFuncBase
{
public:
typedef void (*func)();
VoidFuncWrapper0(func fp) : fp_(fp) { }
void operator()() { fp_(); }
private:
func fp_;
};
template<typename P1>
class VoidFuncWrapper1 : public VoidFuncBase
{
public:
typedef void (*func)(const P1 &);
VoidFuncWrapper1(func fp, const P1 &p1) : fp_(fp), p1_(p1) { }
void operator()() { fp_(p1_); }
private:
func fp_;
P1 p1_;
};
template<typename P1, typename P2>
class VoidFuncWrapper2 : public VoidFuncBase
{
public:
typedef void (*func)(const P1 &, const P2 &);
VoidFuncWrapper2(func fp, const P1 &p1, const P2 &p2)
: fp_(fp), p1_(p1), p2_(p2) { }
void operator()() { fp_(p1_, p2_); }
private:
func fp_;
P1 p1_;
P2 p2_;
};
template<typename R>
class FuncBase
{
public:
virtual R operator()() = 0;
};
template<typename R>
class FuncWrapper0 : public FuncBase<R>
{
public:
typedef R (*func)();
FuncWrapper0(func fp) : fp_(fp) { }
R operator()() { return fp_(); }
private:
func fp_;
};
template<typename R, typename P1>
class FuncWrapper1 : public FuncBase<R>
{
public:
typedef R (*func)(const P1 &);
FuncWrapper1(func fp, const P1 &p1) : fp_(fp), p1_(p1) { }
R operator()() { return fp_(p1_); }
private:
func fp_;
P1 p1_;
};
template<typename R, typename P1, typename P2>
class FuncWrapper2 : public FuncBase<R>
{
public:
typedef R (*func)(const P1 &, const P2 &);
FuncWrapper2(func fp, const P1 &p1, const P2 &p2)
: fp_(fp), p1_(p1), p2_(p2) { }
R operator()() { return fp_(p1_, p2_); }
private:
func fp_;
P1 p1_;
P2 p2_;
};
template<typename R>
R ft(FuncBase<R> func, std::string functionName)
{
unsigned long threadId = getThreadId();
double startTimeMs = fTimer.getMilliseconds();
R result = func();
double duration = fTimer.getMilliseconds() - startTimeMs;
logf("%u %s took %fms", threadId, functionName.c_str(), duration);
return result;
}
void ft(VoidFuncBase func, std::string functionName, int logTimeoutMs)
{
unsigned long threadId = getThreadId();
double startTimeMs = timer.getMilliseconds();
func();
double duration = timer.getMilliseconds() - startTimeMs;
logf("%u %s took %fms", threadId, functionName.c_str(), duration);
}
目前我得到了
“错误:不能将参数'func'声明为抽象类型 'VoidFuncBase'"。
但无论如何,我可能走错了方向。
【问题讨论】:
-
在 c++11 中有一个不错的 std::function。在c++03中,做起来很头疼,因为你必须创建各种模板类和函数
-
@VJovic: 各种,如非类型模板参数、表达式模板、类型特征、奇怪重复的模板模式,...,?
-
没有一种叫做 C/C++ 的语言。
-
我知道没有称为 C/C++ 的语言,但我用它表示我会重视基于 C 或 C++ 的实现。
-
我会建议一种不同的方法来进行分析,就像在 Zoom 中所做的那样。您需要能够读取调用堆栈,并在中断时执行。如果采集了 100 个样本,其中 40% 出现了一条线,那么如果你可以消除这条线,总时间将减少 40%。 (这是 1.67 或 67% 的加速。)因此,它不仅可以找到昂贵的功能,还可以找到昂贵的线路。它不需要超级准确或超级高效。无论如何它都会找到它们,并且递归丝毫不会打扰它。
标签: c++ callback compiler-errors profiling function-pointers