And yes, it boils down to writing data to a message queue. Most of the overhead is probably the call to the hardware timestamp counter.
And yes, it boils down to writing data to a message queue. Most of the overhead is probably the call to the hardware timestamp counter.
That's already ~10 ns, so I'm not sure how they are getting their numbers. If they are timestamping the data when the background thread gets to it that would be pushing even more work to it. It guessing they do or else they could potentially be logging out of order data with multiple threads.
Timestamps will be somewhat inaccurate but it may help performance.
The fastest for nanosecond precision (bonus is this is even sub nanosecond) is just to store the return value of RDTSC and let the background thread figure it all out. You don't even need to precalcuate the freq or epoch offset. Just write a couple logging messages of the rdtsc value and CLOCK_REALTIME and let the post processing figure it out.
To cut down on I/O each log message's timestamp can just be an offset from the last even.
If you are willing to push a lot of work to the background thread and even more to the post processsing step, you really don't need to do very much.
Not sure it matters a lot of to have multiple messages with the same timestamp, since they were added in order you still know which one is older, the problem might arise when you send those logs to a remote place and the order of insert is discarded and the timestamp is used instead.
I assume that when you use a single thread with a queue / ring buffer the order of insertion is kept.
If you have an event loop, it might be acceptable to sample the counter once per iteration, but less than that it becomes too lossy.
You had the OS down-clocking cores to avoid CPUs cooking themselves, causing time to increase an inconsistent rates. Your app queried the clock rate, but unless it kept querying it, the number of cycles was meaninglesss.
ie:
(CPU rate changed to 1GHz)
Query Rate, 1GHz.
(CPU rate changed to 700MHz)
Read start time
Read end time
convert delta into time, using 1GHz rate... not accurate.
or (CPU rate set to 1GHz)
Read start time
Read end time
(CPU rate set to 700MHz)
Query rate, 700Mhz.
convert delta into time, using 700MHz rate... not accurate.
Next you had multicore, and the OS would down-clock or turn off some idle cores, again, perhaps they were throttled to avoid overheating. Again, the clock rate would change dynamically, but per core. Not only did time not increase at a constant pace, but if a thread jumped between cores, time could appear to go backwards!It was a mess. Windows introduced a call to get time in a safe way, as they knew when they changed CPU frequencies. Intel fixed the hardware to use a constant clock after a just a few models, but the damage is done... It's invariant...usually, but not for certain.
You can verify it's invariant through one of the cpuid leaves. There's a feature bit.