I'm looking for:
1: startTime := time.Now()
2: // run something here that takes a while (measured in milliseconds)
3: duration := time.Since(startTime)
However, I need something that is immune to clock time changes. If the time is adjusted between lines 1 and 3, the duration will be inaccurate.
What are some common approaches for solving this problem, and what Go libraries could be relevant?
Thanks :)
That lack of monotonic clock was detailed in issue 12914 (2015)
Since then, in August 2017 and Go 1.9, you now have a transparent Monotonic Time support:
The
time
package now transparently tracks monotonic time in eachTime
value, making computing durations between twoTime
values a safe operation in the presence of wall clock adjustments.
See the package docs and design document for details.
For Linux (AMD64) go uses clock_gettime
with CLOCK_REALTIME
. See the time·now
implementation.
You would want a monotonic clock (CLOCK_MONOTONIC
or CLOCK_MONOTONIC_RAW
), which is a clock that does not go back in time. In Linux the man page explicitly tells you that CLOCK_MONOTONIC
does not guarantee to not leap forward:
This clock is not affected by discontinuous jumps in the system time (e.g., if the system administrator manually changes the clock), but is affected by the incremental adjustments performed by adjtime(3) and NTP.
So, under Linux, the best choice is probably CLOCK_MONOTONIC_RAW
. You may use the clock package mentioned by @MatrixFrog for that. Example:
import (
"fmt"
"github.com/davecheney/junk/clock"
"time"
)
func main() {
start := clock.Monotonic.Now()
// work
end := clock.Monotonic.Now()
duration := end.Sub(start)
fmt.Println("Elapsed:", duration)
}
Further reading: