Golang Monotonic Time: proposal reasons
denniseliteOne of most the important proposals in last Go 1.9 release was the “Monotonic Elapsed Time Measurements in Go”. It solved the main problem of time-related operations when operation system affected the clock tickers.
Common proposal info: https://github.com/golang/proposal/blob/master/design/12914-monotonic.md
Theory
Our сlocks can't work durably without errors. Sometimes you can see when your analog clocks have a couple of minutes delays between more reliable clocks and you can reset it to match the reference. It is a normal practice for us but unfortunately computers have similar problems.
The algorithms of system clock compare and fix local time by higher-accuracy reference clock which located in an available network. If the local clock is observed then it can be slowed a little and if it slightly behind then sped up by counting some ticks twice. Also, for highest accuracy computer may add new algorithms and features to tick generations rules, so, in normal situations, system clocks works perfectly.
But the problem arises if computer clocks are turned off and after launch, the system will have a wrong time before synchronization. And another reason that time tickers may ignore leaps for time fixing and do it in unpredictable moments.
Practice
The problems of system clock starts when we are catching some system time leaps in the Go runtime, as example:
t1 := time.Now() // 10 ms of work t2 := time.Now() // 10 ms of work t3 := time.Now() // 10 ms of work const f = "15:04:05.000" fmt.Println(t1.Format(f), t2.Sub(t1), t2.Format(f), t3.Sub(t2), t3.Format(f))
And the Go 1.8 will return
23:59:59.985 10ms 23:59:59.995 -990ms 23:59:59.005
-990ms? Yes - we got the negative value. Negative value in that case occurred because after 23:59:59.995 point system had delayed next second for synchronization with the higher-accuracy reference clock.
Another case, now we have the timezone changing time in period 1:00 AM - 2:00 AM and we lost time accuracy again because In Go 1.8, the result will:
t1 := time.Now() // 10 ms of work t2 := time.Now() // 10 ms of work t3 := time.Now() // 10 ms of work const f = "15:04" fmt.Println(t1.Format(f), t2.Sub(t1), t2.Format(f), t3.Sub(t2), t3.Format(f))
and return:
00:59 10ms 00:59 10ms 02:00
So you can see that we’ve got a difference in runtime with 61-minute duration but the convenient variant should be
00:59 10ms 00:59 10ms 01:00
Because in runtime we have the only 10ms difference between t2 and t3 difference.