When printing my logs, I want each message to have a time stamp, measuring time since start of the program. Preferably in nanoseconds, though milliseconds are fine as well:
( 110 ns) Some log line
( 1220 ns) Another log line
( 2431 ns) Now for some computation...
(10357 ns) Error!
To my understanding, there three different clocks in the C++ chrono library and two more C-style clocks:
What are the pros and cons for each those for the task described above?
system_clock
is a clock that keeps time with UTC (excluding leap seconds). Every once in a while (maybe several times a day), it gets adjusted by small amounts, to keep it aligned with the correct time. This is often done with a network service such as NTP. These adjustments are typically on the order of microseconds, but can be either forward or backwards in time. It is actually possible (though not likely nor common) for timestamps from this clock to go backwards by tiny amounts. Unless abused by an administrator, system_clock
does not jump by gross amounts, say due to daylight saving, or changing the computer's local time zone, since it always tracks UTC.
steady_clock
is like a stopwatch. It has no relationship to any time standard. It just keeps ticking. It may not keep perfect time (no clock does really). But it will never be adjusted, especially not backwards. It is great for timing short bits of code. But since it never gets adjusted, it may drift over time with respect to system_clock
which is adjusted to keep in sync with UTC.
This boils down to the fact that steady_clock
is best for timing short durations. It also typically has nanosecond resolution, though that is not required. And system_clock
is best for timing "long" times where "long" is very fuzzy. But certainly hours or days qualifies as "long", and durations under a second don't. And if you need to relate a timestamp to a human readable time such as a date/time on the civil calendar, system_clock
is the only choice.
high_resolution_clock
is allowed to be a type alias for either steady_clock
or system_clock
, and in practice always is. But some platforms alias to steady_clock
and some to system_clock
. So imho, it is best to just directly choose steady_clock
or system_clock
so that you know what you're getting.
Though not specified, std::time
is typically restricted to a resolution of a second. So it is completely unusable for situations that require subsecond precision. Otherwise std::time
tracks UTC (excluding leap seconds), just like system_clock
.
std::clock
tracks processor time, as opposed to physical time. That is, when your thread is not busy doing something, and the OS has parked it, measurements of std::clock
will not reflect time increasing during that down time. This can be really useful if that is what you need to measure. And it can be very surprising if you use it without realizing that processor time is what you're measuring.
C++20 adds four more clocks to the <chrono>
library:
utc_clock
is just like system_clock
, except that it counts leap seconds. This is mainly useful when you need to subtract two time_point
s across a leap second insertion point, and you absolutely need to count that inserted leap second (or a fraction thereof).
tai_clock
measures seconds since 1958-01-01 00:00:00 and is offset 10s ahead of UTC at this date. It doesn't have leap seconds, but every time a leap second is inserted into UTC, the calendrical representation of TAI and UTC diverge by another second.
gps_clock
models the GPS time system. It measures seconds since the first Sunday of January, 1980 00:00:00 UTC. Like TAI, every time a leap second is inserted into UTC, the calendrical representation of GPS and UTC diverge by another second. Because of the similarity in the way that GPS and TAI handle UTC leap seconds, the calendrical representation of GPS is always behind that of TAI by 19 seconds.
file_clock
is the clock used by the filesystem
library, and is what produces the chrono::time_point
aliased by std::filesystem::file_time_type
.
One can use a new named cast in C++20 called clock_cast
to convert among the time_point
s of system_clock
, utc_clock
, tai_clock
, gps_clock
and file_clock
. For example:
auto tp = clock_cast<system_clock>(last_write_time("some_path/some_file.xxx"));
The type of tp
is a system_clock
-based time_point
with the same duration
type (precision) as file_time_type
.