Most programs need to know how long a given task takes. The header <chrono> provides tools for precisely and portably obtaining such values.
There is a clock, which tells you how long it has been since some arbitrary starting point in time, a time point, the output of a clock, and a duration, which represents the difference between two time points. The best clock for measuring how long an operation is taking is std::chrono::steady_clock, since it always returns values that never decrease.
The simplest measuring task is to clock a short, simple loop:
#include <iostream>
#include <chrono>
int main()
{
auto start{std::chrono::steady_clock::now()};
int sum{0};
// Increment the value before the expression uses it
for (int i{0}; i < 1000000; ++i)
sum += i;
auto end{std::chrono::steady_clock::now()};
auto elapsed{end - start};
std::cout
<< std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count()
<< '\n';
}
Calling std::chrono::steady_clock::now() will return a time_point, which we store in start. The loop will then accumulate some numbers, after which a second call to now() provides the time_point where we will store the final time in end. Subtracting one time_point from another produces a duration, which we store in elapsed.
We cast this to an integral number of milliseconds using std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).
The count() member function extracts the actual integer number from the cast duration, and we print it.
We can use finer granularities to measure faster events:
#include <iostream>
#include <chrono>
int main()
{
auto start{std::chrono::steady_clock::now()};
int sum{0};
for (int i{0}; i < 1000; ++i)
sum += i;
auto end{std::chrono::steady_clock::now()};
auto elapsed{end - start};
std::cout
// Represent a span of time with a count and unit
<< std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()
<< '\n';
}
The above code is entirely the same except for a cast to std::chrono::microseconds. The number printed will now represent the time taken in microseconds. Some granularities will be too large and yield zero, and some will be too small and give a huge number, but these are the two extremes, for positive time intervals.
steady_clock is only one of several types of clock, but for the purpose of timing interval operations, this is the one you want since its value will never decrease. System clocks will not necessarily work, since they can move forward or backward depending on the OS deciding to adjust them in accordance with the wall clock time.
Subtracting two time points results in a duration, which typically exists as some specific tick count with a particular rate, how much actual time constitutes one tick. To extract a concrete unit like milliseconds or microseconds, we will need to cast it using duration_cast. Without the cast, the program would compile, but a raw std::chrono::duration object printed to standard output shows an implementation defined tick value that is of little use to us.
Everything fits together, therefore, into this pattern: Get a starting time_point, perform your operation, get an ending time_point, subtract the starting from the ending time point to produce a duration, cast to the target units, then print the count.
0 comments
No comments yet. Be the first.