Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between std::system_clock and std::steady_clock?

What is the difference between std::system_clock and std::steady_clock? (An example case that illustrate different results/behaviours would be great).

If my goal is to precisely measure execution time of functions (like a benchmark), what would be the best choice between std::system_clock, std::steady_clock and std::high_resolution_clock?

like image 602
Vincent Avatar asked Nov 07 '12 04:11

Vincent


People also ask

What is std :: Chrono :: steady_clock?

Class std::chrono::steady_clock represents a monotonic clock. The time points of this clock cannot decrease as physical time moves forward and the time between ticks of this clock is constant.

What does std :: Chrono :: System_clock :: now return?

std::chrono::system_clock::now Returns a time point representing with the current point in time.

What is a steady clock?

A steady_clock is a monotonic clock, which means that the time it reports only moves forward.

How accurate is Chrono C++?

Short answer: Not accurate in microseconds and below.


2 Answers

From N3376:

20.11.7.1 [time.clock.system]/1:

Objects of class system_clock represent wall clock time from the system-wide realtime clock.

20.11.7.2 [time.clock.steady]/1:

Objects of class steady_clock represent clocks for which values of time_point never decrease as physical time advances and for which values of time_point advance at a steady rate relative to real time. That is, the clock may not be adjusted.

20.11.7.3 [time.clock.hires]/1:

Objects of class high_resolution_clock represent clocks with the shortest tick period. high_resolution_clock may be a synonym for system_clock or steady_clock.

For instance, the system wide clock might be affected by something like daylight savings time, at which point the actual time listed at some point in the future can actually be a time in the past. (E.g. in the US, in the fall time moves back one hour, so the same hour is experienced "twice") However, steady_clock is not allowed to be affected by such things.

Another way of thinking about "steady" in this case is in the requirements defined in the table of 20.11.3 [time.clock.req]/2:

In Table 59 C1 and C2 denote clock types. t1 and t2 are values returned by C1::now() where the call returning t1 happens before the call returning t2 and both of these calls occur before C1::time_point::max(). [ Note: this means C1 did not wrap around between t1 and t2. —end note ]

Expression: C1::is_steady
Returns: const bool
Operational Semantics: true if t1 <= t2 is always true and the time between clock ticks is constant, otherwise false.

That's all the standard has on their differences.

If you want to do benchmarking, your best bet is probably going to be std::high_resolution_clock, because it is likely that your platform uses a high resolution timer (e.g. QueryPerformanceCounter on Windows) for this clock. However, if you're benchmarking, you should really consider using platform specific timers for your benchmark, because different platforms handle this differently. For instance, some platforms might give you some means of determining the actual number of clock ticks the program required (independent of other processes running on the same CPU). Better yet, get your hands on a real profiler and use that.

like image 62
Billy ONeal Avatar answered Sep 22 '22 00:09

Billy ONeal


Billy provided a great answer based on the ISO C++ standard that I fully agree with. However there is another side of the story - real life. It seems that right now there is really no difference between those clocks in implementation of popular compilers:

gcc 4.8:

#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC    ... #else   typedef system_clock steady_clock; #endif   typedef system_clock high_resolution_clock; 

Visual Studio 2012:

class steady_clock : public system_clock {   // wraps monotonic clock public:   static const bool is_monotonic = true;    // retained   static const bool is_steady = true; };  typedef system_clock high_resolution_clock; 

In case of gcc you can check if you deal with steady clock simply by checking is_steady and behave accordingly. However VS2012 seems to cheat a bit here :-)

If you need high precision clock I recommend for now writing your own clock that conforms to C++11 official clock interface and wait for implementations to catch up. It will be much better approach than using OS specific API directly in your code. For Windows you can do it like that:

// Self-made Windows QueryPerformanceCounter based C++11 API compatible clock struct qpc_clock {   typedef std::chrono::nanoseconds                       duration;      // nanoseconds resolution   typedef duration::rep                                  rep;   typedef duration::period                               period;   typedef std::chrono::time_point<qpc_clock, duration>   time_point;   static bool is_steady;                                                // = true   static time_point now()   {     if(!is_inited) {       init();       is_inited = true;     }     LARGE_INTEGER counter;     QueryPerformanceCounter(&counter);     return time_point(duration(static_cast<rep>((double)counter.QuadPart / frequency.QuadPart *                                                 period::den / period::num)));   }  private:   static bool is_inited;                                                // = false   static LARGE_INTEGER frequency;   static void init()   {     if(QueryPerformanceFrequency(&frequency) == 0)       throw std::logic_error("QueryPerformanceCounter not supported: " + std::to_string(GetLastError()));   } }; 

For Linux it is even easier. Just read the man page of clock_gettime and modify the code above.

like image 33
Mateusz Pusz Avatar answered Sep 25 '22 00:09

Mateusz Pusz