runtime: time.Sleep takes more time than expected #44343
Comments
It looks like this happened in 8fdc79e. https://go-review.googlesource.com/c/go/+/232298 CC: @ChrisHines |
This is reproducible with a trivial benchmark in time package: func BenchmarkSimpleSleep(b *testing.B) {
for i := 0; i < b.N; i++ {
Sleep(50*Microsecond)
}
} amd64/linux, before/after http://golang.org/cl/232298:
|
For reference, across different sleep times:
|
Looking at the 100µs, the immediate problem is the delay resolution in Prior to http://golang.org/cl/232298, 95% of timer expirations in the 100µs case are detected by After http://golang.org/cl/232298, this path is gone and the wakeup must come from I'm not sure why I'm seeing ~500µs on the 10µs and 50µs benchmarks, but I may have bimodal distribution where ~50% of cases a spinning M is still awake long enough to detect the timer before entering I'm also not sure why @egonelbre is seeing ~14ms on Windows, as that also appears to have 1ms resolution on |
I think the ideal fix to this would be to increase the resolution of As it happens, Linux v5.11 includes In the past, I've also prototyped changing the Both of these are Linux-specific solutions, I'd have to research other platforms more to get a sense of the options there. We also may just want to bring the |
I guess that Perhaps when |
While working on CL232298 I definitely observed anecdotal evidence that the netpoller has more latency than other ways of sleeping. From #38860 (comment):
I didn't try to address that in CL232298 primarily because it was already risky enough that I didn't want to make bigger changes. But an idea for something to try occurred to me back then. Maybe we could improve the latency of non-network timers by having one M block on a I haven't fully gauged how messy that would get. Questions and concerns:
One other oddity that I noticed when testing CL232298: The linux netpoller sometimes wakes up from the timeout value early by a several microseconds. When that happens |
As somewhat of a combination of these, one potential option would be to make
Hm, this sounds like another bug, or perhaps a spurious |
It seems that on Windows, |
My first thought on the Windows behavior is that somehow |
That could be, but I was logging at least some of the calls to netpollBreak as well and don't recall seeing seeing that happen. I saved my logging code in case it can help. https://github.com/ChrisHines/go/tree/dlog-backup |
For reference, output on my Windows 10:
A totally different results from the #44343 (comment).
|
@vellotis this could be because there's something running in the background changing Windows timer resolution. This could be some other Go service/binary built using older Go version. Of course there can plenty of other programs that may change it. You can use https://github.com/tebjan/TimerTool to see what the current value is. There's some more detail in https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted. |
This seems to be a regression with Go 1.16
time.Sleep
.What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
hrtime
is a package that usesRDTSC
for time measurements.Output on Windows 10:
Output on Linux (Debian 10):
The time granularity shouldn't be that bad even for Windows. So, there might be something going wrong somewhere.
The text was updated successfully, but these errors were encountered: