calculating time elapsed in C++

10,987

Solution 1

Using <chrono>, the code you need could look like this:

using clock = std::chrono::system_clock;
using sec = std::chrono::duration<double>;
// for milliseconds, use using ms = std::chrono::duration<double, std::milli>;

const auto before = clock::now();

someFunctionToMeasure();

const sec duration = clock::now() - before;

std::cout << "It took " << duration.count() << "s" << std::endl;

NB: Thanks to Howard for his helpful comments for the above.

If you need this snippet multiple times and start/end are approximately entry and exit points of the scope in which you invoke someFunctionToMeasure(), it might make sense to wrap it into a utility class that makes the two calls to now() in constructor and destructor.

Solution 2

Just want to throw in the modern approach to timing any callable using <chrono> and the handy std::invoke from C++17. Works on members, lambdas or free function, or any other callable.

// Just for convenience
using Seconds = std::chrono::duration<double>;

// Measure how much time the given function takes to execute using chrono
// Pass the function name, then all relevant arguments, including the object as the first if it's a member function

template<typename Function, typename... Args>
Seconds measure(Function&& toTime, Args&&... a)
{
    auto start{std::chrono::steady_clock::now()};                                                   // Start timer
    std::invoke(std::forward<Function>(toTime), std::forward<Args>(a)...);  // Forward and call
    auto stop{std::chrono::steady_clock::now()};                                                   // Stop timer
    return (stop - start);
}

This will return the time the function took to execute. If you also need the return value, you could make a std::pair with the Seconds and the return value since std::invoke will correctly return what the callable returns.

Then you can use it like this:

auto t1 = measure(normalFunction);
auto t2 = measure(&X::memberFunction, obj, 4);
auto t3 = measure(lambda, 2, 3);

On a free function, member function and lambda respectively.

Solution 3

Source: http://en.cppreference.com/w/cpp/chrono/c/clock

  1. The clock is only keeping track of the time that has passed on the process the clock is executing on. So your sample code is keeping track of how much CPU time it took for your function to execute in. This is notably different from keeping track of real time, because the process your function is running on could be preempted and the cpu could execute other code for some time while your function is waiting to finish.

  2. To answer your second question it may help to clarify what you mean by "better". It sounds like you wanted to track the amount of time that your function executed for, and from my understanding this code accomplishes that task. If you wanted to track the amount of time in real time the other answers give examples of that.

Share:
10,987

Related videos on Youtube

mereth
Author by

mereth

Updated on June 04, 2022

Comments

  • mereth
    mereth about 2 years

    I need to calculated time elapsed of my function. Right now i am using std::clock and from what i understand this is measuring CPU time, which could be different from real time.

    std::clock_t start;
    double duration;
    
    start = std::clock();
    
    someFunctionToMeasure();
    
    duration = (std::clock() - start) / (double)CLOCKS_PER_SEC;
    

    So there are 2 things i'd like to know

    1. How does std::clock exactly work? is it just measuring CPU when its computing that function?

    2. Is there a better way to measure time elapsed of computing my function?

  • TMS
    TMS almost 5 years
    Is the final answer is millseconds or seconds?
  • lubgr
    lubgr almost 5 years
    @TMS milliseconds.
  • TMS
    TMS almost 5 years
    But you are dividing by 1000?
  • lubgr
    lubgr almost 5 years
    @TMS Sorry, you're right of course. The snippet is actually wrong as it outputs "ms". Let me correct this...
  • Howard Hinnant
    Howard Hinnant almost 5 years
    One could/should implicitly convert once to duration<double> instead of explicitly converting to milliseconds and then manually converting to double-based seconds. It is best to let <chrono> do the conversions for you in order to avoid errors. And once we get C++20, you'll be able to drop the .count() << "s". The library will add the s for you.
  • lubgr
    lubgr almost 5 years
    @HowardHinnant Thanks for the hint, that makes sense! The cast/count() sequence should be clearer now.
  • Howard Hinnant
    Howard Hinnant almost 5 years
    Looks much better! This can be further simplified down to const sec duration = clock::now() - before;. The advantage to the simplification is that truncation is a source of errors. So if you only use duration_cast when you are actually truncating, you'll have fewer places to inspect when searching for a bug you think is related to truncation.
  • lubgr
    lubgr almost 5 years
    @HowardHinnant Ok thanks again, I took that into account. Also skimmed through cppref. on the return type of operator - for two time_points instances, the common_type specialization... which made me realize I've at least one of your <chrono> talks on my watchlist. I should shift them w.r.t. their priority now :)