-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
time: Timer ticks at incorrect time. #19810
Comments
This program doesn't do what you think it does:
The
instead. |
@rsc changing the code to what you suggested still has the same issue, where the ticker is ticking later than when it should. |
I don't know, this seems to work fine for me:
|
Note that it does generate a lot of garbage tickers that never stop and fill up the timer heap, so they will slow down your program over a very long time. Really the code should t.Stop() before starting a new one, or use time.After. But it works fine for me. |
Also note that time.Ticker already takes care of firing multiple times and making sure it stays aligned to its initial start. So this would be even easier:
|
@rsc
On my Computer
|
@GrimTheReaper Try using current Go master instead of Go 1.8. It will show the monotonic times in the print too. The most likely answer is that the Azure VM is running its monotonic clock at 5s/5s but the real time clock at 4.9s/5s, for whatever reason. If you don't have Go master handy for building, I've attached a zip with a Linux binary of the program. |
@rsc I'll try that out, and post back results. Thank you for having the time to help btw. 👍 |
Here are the results. Azure VM:
|
It does seem that for whatever reason your VM's monotonic timer is running (1+2/99)X faster than wall time, assuming wall time is correct. It's not that uncommon for virtualization to affect the different clocks differently, for what it's worth, although I don't have any guesses about where 2/99 comes from. |
@rsc reading other blog post and talking to a few people who use Azure on a daily bases, it seems that Microsoft's VMs will always be off, and other people have this same issue. Although this is no longer a Golang issue, do you have any advice on what I should do from here on out? |
Instead of using a repeating ticker I would suggest using either time.Sleep or time.After (which only ticks once) and then recalculate the wall clock delta on each iteration. Like you were doing in the first example, but without time.Ticker and without the range loop. Using sleep it would look like:
If you're doing 3 minute sleeps then you're going to wake up about 3.5 seconds early due to the sleep running faster than wall time. If that is important, you could assume the Azure constant is stable (it seems quite stable in the test at least) and uncomment the adjustment in waitUntilAligned. Or you could go super-fancy and have the implementation watch the skew and adjust (comment out fakeAzure = true for real use, although it will work either way). If the clock is fast the ticks will still always come slightly early even corrected. You could ask for the tick to come at an offset from the actual aligned time to shove it forward. The code below tries for 5s aligned + 0.01s offset (also at https://play.golang.org/p/jSpAiz6piq):
|
@rsc |
What version of Go are you using (
go version
)?go version go1.8 linux/amd64
What operating system and processor architecture are you using (
go env
)?What did you do?
https://play.golang.org/p/ksmG70ZspO
Playground wont work, as the application takes too long to do anything.
This application is expected to tick at every 3rd minute, divisible by 3, at the zero second. The main func calls the func
runningRoutine
which then starts a ticker which is scheduled to report back on chanticker.C
.What did you expect to see?
What did you see instead?
This is the first tick, which it drifts, but the drifting gets worse, up to a minute, after a few ticks.
The text was updated successfully, but these errors were encountered: