I was wondering if it would be a good idea to use the steady_clock class (in the C++ std libraries) for game timing. What are the pros/cons of using it as opposed to using a game library's timing mechanism?
-
\$\begingroup\$ Perhaps you should take a look into the source code of a game library's timing functions; behind them you should simply find some system-specific API calls, nothing custom or arcane. The game library should simply be using the best standard timer choice, that is, one which is high resolution and accurate. \$\endgroup\$– RicketCommented Nov 25, 2012 at 4:40
3 Answers
As far as I understood std::chrono you cant be sure to get a high resolution timer with std::steady_clock. So you might loose some accuracy on some system if the high resolution timer is not available as steady clock. I considered that too a while ago but than I read about steady clock and high resolution. I just can't find the reference at the moment.
Edit:
Here it is http://www.cplusplus.com/reference/chrono/high_resolution_clock/ there you can see that the high resolution clock has a is_steady member. So for me it seems you can also get unsteady high resolution clocks. And on my system this member returned false. If you are fine with low resolution I think theres nothing against using steady_clock.
Try this:
typedef std::conditional<
std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock,
std::chrono::steady_clock >::type ClockType;
Also note, that sometimes steady_clock
is not steady, so include this so there are no surprises:
static_assert( ClockType::is_steady,
"Clock is not monotonically-increasing (steady).");
Note that Steady clock is not enabled by default on GCC4.7 (and others, I'm sure), but you can enable it with a flag.
Using the game's timing library, if one is provided, has an advantage in terms of consistency. If you only interact with your own timing, this may not be important, but if you ever have to compare a time that you measured against a time reported by the game engine, it's very helpful to be using the same clocks.
If you choose to use the C++11 timers anyway, there's a choice you have to make. You have to choose between high_resolution_clock
and steady_clock
. There is no one-size-fits-all choice here, you have to pick the right one for your application. high_resolution_clock
is typically very high resolution (duh) and very light weight because its job is to measure things as precisely as possible. A common implementation of it is to read the processor's instruction-count register: very fast, very high resolution. However, there's no guarantees that the rate of these ticks is very reliable. In particular, some implementations can change speed significantly if the CPU is put into a low power mode which decreases the CPU frequency. There's some odd behaviors that have shown up in cases where a laptop does some processing, then stops and waits for a few hundred milliseconds for the next bit of processing. Meanwhilem the OS drops the CPU frequency to conserve power. This slows the high_resolution_clock
on this particular OS/platform, and the program wakes up late, missing its timing window.
steady_clock
is guaranteed to not have this problem. However, in trade it has to be a more "heavy" clock in terms of processing work. While a high_resolution_clock
may just read a register, a steady clock may need to make a system call to go get the "real" time.
If you're measuring very tiny amounts of time (such as profiling the cost of a block of code), then high_resolution_clock
is the correct way to go. If you need the user to feel like your interactions are actually occurring "on time," you should pay the extra price to use steady_clock
so that the measured time is representative of real time.
What about system_clock
you say? You can use that too. However, one of the greats of C++ (I believe it was Herb Sutter) has stated that he believes system clock should be removed for the following reasons:
- On all existing implementations,
system_clock
is a typedef forsteady_clock
orhigh_performance_clock
. - You don't know which clock you're getting with
system_clock
, so you might as well take the extra time to figure out which clock you really wanted, and use it instead.
-
\$\begingroup\$ I believe it's the other way around. "Class std::chrono::high_resolution_clock represents the clock with the smallest tick period provided by the implementation. It may be an alias of std::chrono::system_clock or std::chrono::steady_clock, or a third, independent clock." --en.cppreference.com/w/cpp/chrono/high_resolution_clock \$\endgroup\$– RileyCommented Aug 9, 2019 at 3:31
-
\$\begingroup\$ Nonsense see:
using high_resolution_clock = system_clock;
In implementation and documentation... \$\endgroup\$– GelldurCommented Mar 19, 2020 at 18:23 -
\$\begingroup\$ @DawidDrozd C++ is permitted to have legacy functionality which was thought to be useful at one time. After all, that's why "auto" was a reserved keyword before we repurposed it. \$\endgroup\$ Commented Mar 19, 2020 at 19:35