Fruits

Precision is costly

As you saw in our previous post getting a timestamp as precise as possible is expensive in precious cycles. We do it only when we really need it because we really care about writing the world fastest database.

Fortunately, since C++ 11, std::chrono will be happy to provide you with timestamps and a full set of timing routines and time related functions.

As you can see, three clocks are provided:

  1. system_clock (the system clock, quite precise in most implementations I’ve inspected);
  2. steady_clock (a monotonic clock);
  3. highresolutionclock (the clock with the shortest tick period available).

Now, there are some catches:  highresolutionclock isn’t necessarily more precise than systemclock (and may not be the most precise clock you can get on an OS) and timesince_epoch() doesn’t do exactly what you think it does.

On the actual precision

For example Visual Studio’s implementation is based on GetSystemTimePreciseAsFileTime (you’ve got to love Windows API functions name), which is quite precise but not as precise as Windows can be (it is insufficient for example for the use case of our high resolution timestamp).

That means that when using highresolutionclock on Windows you are getting the most precise clock of the STL implementation, not the most precise clock of the OS.

If you need more precision, you need to use QueryPerformanceCounter.

On the result of timesinceepoch

If you, like me, don’t read carefully the documentation, you might believe that timesinceepoch returns an UNIX epoch of your time_point. Let’s read  the documentation together:

Return value: The amount of time between this time_point and the clock's epoch

Let’s read it again:

Return value: The amount of time between this time_point and the clock's epoch

Not UNIX epoch, but the clock’s epoch, which in many cases is the UNIX epoch. Feeling lost?

I got bitten by this when discovering that the implementation of libc++ highresolutionclock is the only (tested) implementation that isn’t based on UNIX epoch.

In order to have a proper UNIX epoch, you must use systemclock totimet, don’t assume timesince_epoch is UNIX epoch, even if it is in your implementation.