C++ 如何为类的每个方法添加计时器?
如何“隐式”为类的每个方法(不包括构造函数和析构函数)添加某种计时器 我现在为每种课堂方法做的是:C++ 如何为类的每个方法添加计时器?,c++,boost,timer,C++,Boost,Timer,如何“隐式”为类的每个方法(不包括构造函数和析构函数)添加某种计时器 我现在为每种课堂方法做的是: void MyClass::SomeFunc() { cout << __PRETTY_FUNCTION__ <<endl; boost::timer::cpu_timer timer; //Some code boost::timer::cpu_times elapsed = timer.elapsed(); cout <
void MyClass::SomeFunc()
{
cout << __PRETTY_FUNCTION__ <<endl;
boost::timer::cpu_timer timer;
//Some code
boost::timer::cpu_times elapsed = timer.elapsed();
cout << __PRETTY_FUNCTION__ << " : WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl;
}
假设这两部分代码的行为应该是等效的。使用RAII几乎可以实现这一点:
struct FunctionLogger {
FunctionLogger(const char* func)
: m_func(func)
{
cout << func <<endl;
}
~FunctionLogger() {
boost::timer::cpu_times elapsed = timer.elapsed();
GSULOG << m_func << " : WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl;
}
const char* m_func;
boost::timer::cpu_timer timer;
};
当然,如果您喜欢宏:
#define FL FunctionLogger _(__PRETTY_FUNCTION__)
void MyClass::SomeFunc()
{
FL;
//Some code
}
如果你正在为这类事情寻找工业级的解决方案,艺术的术语是。但是C++没有直接支持。几乎可以使用RAII:< /P>实现这一点。
struct FunctionLogger {
FunctionLogger(const char* func)
: m_func(func)
{
cout << func <<endl;
}
~FunctionLogger() {
boost::timer::cpu_times elapsed = timer.elapsed();
GSULOG << m_func << " : WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl;
}
const char* m_func;
boost::timer::cpu_timer timer;
};
当然,如果您喜欢宏:
#define FL FunctionLogger _(__PRETTY_FUNCTION__)
void MyClass::SomeFunc()
{
FL;
//Some code
}
如果你正在为这类事情寻找工业级的解决方案,艺术的术语是。但是它不是C++直接支持的。你所要做的就是大家所知的剖析(获取每个函数调用的持续时间)和仪器(将代码注入到函数中以获得更详细,但可能不太准确的时序信息)。
到目前为止最好的方法是不要自己动手,而是在剖析器(一个现成的应用程序,它可以自动进行计时和插装,并且可以选择自动进行,而不会污染源代码)下运行代码。您试图做的就是所谓的剖析(获取每个函数调用的持续时间)和插装(向函数中注入代码以获得更详细但可能不太准确的计时信息)
到目前为止最好的方法不是自己动手,而是在探查器下运行代码(一个现成的应用程序,可以自动执行计时和插装,并且可以选择自动执行,所有这些都不会污染源代码。)如果您希望避免修改代码,并且愿意牺牲
\uu PRETTY\u函数\uuuu
输出。您可以通过计时句柄访问类来实现这一点
首先,您定义一个RAII类用于计时,类似于John Zwinck的回答:
template<typename T>
struct TimingDecorator {
T *ptr_;
boost::timer::cpu_timer timer;
TimingDecorator (T* ptr) : ptr_(ptr) {}
~TimingDecorator () {
boost::timer::cpu_times elapsed = timer.elapsed();
GSULOG << " : WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl;
}
T* operator->() { return ptr_; }
T const * operator->() const { return ptr_; }
};
如果您希望避免修改代码,并且愿意牺牲
\uu PRETTY\u函数\uuuu
输出。您可以通过计时句柄访问类来实现这一点
首先,您定义一个RAII类用于计时,类似于John Zwinck的回答:
template<typename T>
struct TimingDecorator {
T *ptr_;
boost::timer::cpu_timer timer;
TimingDecorator (T* ptr) : ptr_(ptr) {}
~TimingDecorator () {
boost::timer::cpu_times elapsed = timer.elapsed();
GSULOG << " : WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl;
}
T* operator->() { return ptr_; }
T const * operator->() const { return ptr_; }
};
稍微改变一下计划,您也可以使用:
template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
return [f=std::forward<F>(f), task](auto&&... args) {
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
Caption task;
~measure() { GSU_LOCK << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), task };
return f(std::forward<decltype(args)>(args)...);
};
}
注意:您还可以让lambda为不同的通话积累数据,并报告总计/平均值。稍微反转一下计划,您也可以使用:
template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
return [f=std::forward<F>(f), task](auto&&... args) {
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
Caption task;
~measure() { GSU_LOCK << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), task };
return f(std::forward<decltype(args)>(args)...);
};
}
注意,你也可以让LAMBDA为不同的调用积累数据,并报告总数/平均值。
比我把代码作为lambda运行到函数的想法要好得多。你可以考虑使用“\n”而不是Endl,顶部避免刷新缓冲器。@乔纳斯:也许,但是你应该建议OP,而不是我。他到底想要还是NEE。我不知道。我只是复制了相同的行为。比我把代码作为lambda运行到函数的想法要好得多。你可以考虑使用‘\n’而不是Endl,最好避免刷新缓冲区。@乔纳斯:也许,但是你应该建议OP,而不是我。不管他想要还是需要刷新,我都不知道。我只是复制。添加了一个生成类似于497455µs中完成的(main.cpp:25 std::getline(std::cin,line)的输出的程序。
添加了一个生成类似于(main.cpp:25 std::getline(std::cin,line)的输出的程序。
MYCLASS_TIME_FUNC(obj_timing, SomeFunc2)(/* params for SomeFunc2 */);
template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
return [f=std::forward<F>(f), task](auto&&... args) {
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
Caption task;
~measure() { GSU_LOCK << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), task };
return f(std::forward<decltype(args)>(args)...);
};
}
timed_rand = time("Generate a random number", &::rand);
for (int i = 0; i<10; ++i)
std::cout << timed_rand() << " ";
#include <iostream>
#include <chrono>
using namespace std::literals::string_literals;
#define GSU_LOG std::clog
template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
return [f=std::forward<F>(f), task](auto&&... args) -> decltype(auto) {
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
Caption task;
~measure() { GSU_LOG << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), task };
return f(std::forward<decltype(args)>(args)...);
};
}
#define TIMED(expr) (timed(__FILE__ + (":" + std::to_string(__LINE__)) + " " #expr, [&]() -> decltype(auto) {return (expr);})())
int main() {
std::string line;
while (TIMED(std::getline(std::cin, line))) {
std::cout << "Simple arithmetic: " << TIMED(42 * TIMED(line.length())) << "\n";
}
}
$ clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp
$ for a in x xx xxx; do sleep 0.5; echo "$a"; done | ./a.out
-- (main.cpp:25 std::getline(std::cin, line) completed in 497455µs)
-- (main.cpp:26 line.length() completed in 36µs)
-- (main.cpp:26 42 * TIMED(line.length()) completed in 106µs)
Simple arithmetic: 42
-- (main.cpp:25 std::getline(std::cin, line) completed in 503516µs)
-- (main.cpp:26 line.length() completed in 14µs)
-- (main.cpp:26 42 * TIMED(line.length()) completed in 42µs)
Simple arithmetic: 84
-- (main.cpp:25 std::getline(std::cin, line) completed in 508554µs)
-- (main.cpp:26 line.length() completed in 14µs)
-- (main.cpp:26 42 * TIMED(line.length()) completed in 38µs)
Simple arithmetic: 126
-- (main.cpp:25 std::getline(std::cin, line) completed in 286µs)