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:
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:
System.nanoTime()
, System.currentTimeMillis()
would be equivalent to time.Now()
and is wrongSystem.Diagnostics.Stopwatch
QueryPerformanceCounter
and QueryPerformanceFrequency
std::chrono::steady_clock
, or std::chrono::high_resolution_clock
when its is_steady
member constant is true
performance.now()
, while the use of new Date()
is wrongWhat is the correct way to precisely measure execution time in Go?
⏲️ Measure execution time in Go Before the function, you need to record the current time using time. Now() . Then, after executing the measured block, you can check how much time has elapsed since this time using time. Since() function.
Golang == operator compares not only time instant but also the Location and the monotonic clock reading. time. Duration has a base type int64. Duration represents the elapsed time between two instants as an int64 nanosecond count”. The maximum possible nanosecond representation is up to 290 years.
time. Duration is a type having int64 as its underlying type, which stores the duration in nanoseconds. The above works because 100 is an untyped constant, and it can be converted automatically to time. Duration which has int64 underlying type.
Package time
Monotonic Clocks
Operating systems provide both a “wall clock,” which is subject to changes for clock synchronization, and a “monotonic clock,” which is not. The general rule is that the wall clock is for telling time and the monotonic clock is for measuring time. Rather than split the API, in this package the Time returned by time.Now contains both a wall clock reading and a monotonic clock reading; later time-telling operations use the wall clock reading, but later time-measuring operations, specifically comparisons and subtractions, use the monotonic clock reading.
For example, this code always computes a positive elapsed time of approximately 20 milliseconds, even if the wall clock is changed during the operation being timed:
start := time.Now() ... operation that takes 20 milliseconds ... t := time.Now() elapsed := t.Sub(start)
Other idioms, such as time.Since(start), time.Until(deadline), and time.Now().Before(deadline), are similarly robust against wall clock resets.
Starting with Go 1.9 (released August 24, 2017), Go uses a monotonic clock for durations.
See Proposal: Monotonic Elapsed Time Measurements in Go.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With