What is the correct way to precisely measure a time duration in Go? Most application just use the standard time package and the following approach:
var startTime = time.Now()
doSomeHardWork()
var duration = time.Since(startTime) // or: time.Now() - startTime
However, time.Now()
returns the current system time, which leads to two flaws:
- If the system time is changed during the measurement (for example due to a time zone change (DST) or a leap second), the resulting duration is also wrong.
The system time can tick deliberately faster or slower than the real time. This always happens when the operating system synchronizes the internal clock with NTP time servers (which might happen several times an hour!)
From MSDN:
[The time service] adjusts the local clock rate to allow it to converge toward the correct time. If the time difference between the local clock and the [accurate time sample] is too large to correct by adjusting the local clock rate, the time service sets the local clock to the correct time.
If the system time changes (either manually or due to DST), it might be possible to detect the invalid duration and discard it. But if the system clock ticks e.g. 10% faster to synchronize with world-time, it is practically impossible to detect. That's intended behaviour and how the system clock is designed.
For that reason, most other languages offer a dedicated API for measuring durations:
- Java has
System.nanoTime()
,System.currentTimeMillis()
would be equivalent totime.Now()
and is wrong - C# has
System.Diagnostics.Stopwatch
- C/C++ on Windows has
QueryPerformanceCounter
andQueryPerformanceFrequency
- C++11 and up have
std::chrono::steady_clock
, orstd::chrono::high_resolution_clock
when itsis_steady
member constant istrue
- JavaScript has
performance.now()
, while the use ofnew Date()
is wrong
What is the correct way to precisely measure execution time in Go?