greole
greole

Reputation: 4771

timing of multiple function calls

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

Upvotes: 1

Views: 1435

Answers (2)

R Sahu
R Sahu

Reputation: 206577

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.

Upvotes: 0

Jarod42
Jarod42

Reputation: 217235

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);});

Upvotes: 4

Related Questions