问题
Coming from python I am trying to find a way to time several function calls in a c++ code. So far I am using this.
void my_func(/*some args*/) {
clock_t t_begin = std::clock();
// code
clock_t t_end = std::clock();
double elapsed_secs_U = double(t_end - t_begin) / CLOCKS_PER_SEC;
}
But this is highly repetitive. And I would like to have something like a function wrapper so that I can write:
void timer(func, *args) {
clock_t t_begin = std::clock();
func(*args)
clock_t t_end = std::clock();
double elapsed_secs_U = double(t_end - t_begin) / CLOCKS_PER_SEC;
}
which could be used like:
timer(compute_a, a, b)
timer(compute_b, b, c)
Is there any way to achieve this in C++?
PS: I need the timings in productive runs, thus I dont want to recompile my code with profiling flags and stick it into Valgrind or any other tool
回答1:
Using variadic template, you may do something like:
template <typename F, typename ... Ts>
void timer(F f, Ts&&...args) {
clock_t t_begin = std::clock();
f(std::forward<Ts>(args)...);
clock_t t_end = std::clock();
double elapsed_secs_U = double(t_end - t_begin) / CLOCKS_PER_SEC;
}
But simply
template <typename F>
void timer(F f) {
clock_t t_begin = std::clock();
f();
clock_t t_end = std::clock();
double elapsed_secs_U = double(t_end - t_begin) / CLOCKS_PER_SEC;
}
should do the job, and pass capturing lambda when you need to pass argument:
timer([&](){ compute_b(b, c);});
回答2:
I have used this pattern in the past. This captures the total time spent in a function for the entire life of the program, not the time spent in one call.
struct FunctionTimer
{
FunctionTimer(std::string const& fname) : fname_(fname), totalTime_(0) {}
~FunctionTimer()
{
std::cout << "Total time in " << fname_ << ": " << totalTime_ << std::endl;
}
std::string fname_;
double totalTime_;
};
struct TimeAccumulator
{
TimeAccumulator(FunctionTimer& timer) : timer_(timer), begin_(std::clock()) {}
~TimeAccumulator()
{
clock_t end = std::clock();
double elapsed_secs = double(end - begin_) / CLOCKS_PER_SEC;
timer_.totalTime_ += elapsed_secs;
}
clock_t begin_;
FunctionTimer& timer_;
};
void my_func(/*some args*/)
{
static FunctionTimer timer("my_func");
TimeAccumulator acc(timer);
// code
}
If you would like to create a wrapper function for timing purposes and leave the rest of the functions untouched, some template magic might do the trick. I have to think about the details of how such a function template can be implemented.
来源:https://stackoverflow.com/questions/26136319/timing-of-multiple-function-calls