Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Store timestamps in nanoseconds c++

My goal is to store timestamps in the range of nanoseconds. Let's say that I have two machines that needs to communicate, at precisely what time a task is done.

Let's just for the sake of the question, say that they a synchronized clocks.
Machine A stores its local time when it's done. Machine B transmits to A, at which time it is done. Machine A then calculates the difference.

My problem is, that the timedifference can actually be up to 60 seconds, but also down to .25ms. So I need to store the time in such a manner, that I can handle both, and calculate the timedifference.

Since time since epoch in nanoseconds is such a big number, I don't think I can store that in any variable that I know of.

How would you tackle this situation? My current though is, that I probably (somehow) could scale the time since epoch in ns down to the bits representing 1 minute, though I have no idea how to do that.

Hope you can help.

Best regards

like image 856
Benjamin Larsen Avatar asked Apr 17 '17 12:04

Benjamin Larsen


2 Answers

Just use a 64-bit integer, signed (int64_t) or unsigned (uint64_t), and you'll be all fine.

The 64-bit space is really huge. It is not only enough to store time differences, but even to store absolute time values, which are usually measured as time passed since 1970-01-01 midnight.

For example, right now the number of seconds since 1970-01-01 is roughly:

1492432621.123456789

In nano-seconds, this is:

1492432621123456789

For comparison, the largest signed 64-bit integer value is:

9223372036854775807

This corresponds roughly to 2262-04-12, a date at which you almost certainly won't be alive anymore.

However, if you are still concerned by the possibility that your software runs for more than two centuries, won't be improved during that time, and will eventually crash, then you should either use unsigned 64-bit integers, which will give it some more centuries, or you should use 128-bit integers, which are almost certainly safe until the universe dies. Note that 128-bit integers are supported by all modern 64-bit architectures (__int128 or unsigned __int128), so you can safely use them, unless, of course, you need to support legacy 32-bit systems. Or 16-bit systems. 8-bit, anyone?

like image 168
vog Avatar answered Nov 16 '22 07:11

vog


I recommend using std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>. You can make this much prettier with type aliases. For example:

template <class Duration>
    using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;
using sys_nanoseconds = sys_time<std::chrono::nanoseconds>;

sys_nanoseconds now = std::chrono::system_clock::now();

This gets you the same range as the currently accepted answer (int64_t), but adds type-safety. An int64_t might mean a time point, or a time duration. sys_nanoseconds can mean only a time_point, and will result in a compile time error if used like a time duration.

For example it is a compile-time error to add two sys_nanoseconds together. But you can subtract two sys_nanoseconds and the resultant type is std::chrono::nanoseconds.

Your range (before overflow/underflow) will be:

1677-09-21 00:12:43.145224192 to 2262-04-11 23:47:16.854775807

To get a larger range with nanosecond precision is of questionable value, but can be done like this on platforms that support 128 bit types:

using nano128 = std::chrono::duration<__int128_t, std::nano>;
using sys_nano = sys_time<nano128>;

Now your range is far greater than +/- the age of the universe.

Note that on some platforms, std::chrono::system_clock::now() will not report with an accuracy of nanoseconds. So storing nanosecond timestamps may be overkill. However it is trivial to take the above code and change it to whatever units you want.

On macOS, system_clock::now() reports microseconds, which will have 1000 times the range of nanoseconds. On Windows system_clock::now() reports in units of 1/10 of a microseconds:

using win_sys_duration = std::chrono::duration<std::int64_t,
                                               std::ratio<1, 10'000'000>>;
using win_sys_time_point = sys_time<win_sys_duration>;

And on gcc, system_clock::now() reports nanoseconds.

like image 38
Howard Hinnant Avatar answered Nov 16 '22 06:11

Howard Hinnant