-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
testing: benchmark is using low resolution time on Windows #31160
Comments
I could make an easy patch like I did in https://github.com/rakyll/hey/blob/master/requester/now_windows.go#L24. However since |
As a more practical example:
As we vary benchtime it shows quite a significant timing error:
|
Related: #29714 |
CC @mpvl @josharian |
Ping. I could make a PR and discuss a specific fix, if that's requires less effort from core maintainers. |
I don't have much to say about this. A higher resolution benchmarking timer certainly seems desirable. What are the downsides? cc @alexbrainman for windows |
Some duplicated code for windows and handling for other platforms to be compatible with that. Specifically the Line 381 in 9b6e9f0
testing package.
|
We could use //go:linkname to get access to it. Or an internal package, perhaps. |
After poking it a bit it seems using Usually the way to convert QPC value is https://github.com/golang/go/blob/master/src/runtime/os_windows.go#L447 Ideas so far:
1 seems the smallest and easiest change. 2 requires adjusting things inside runtime... also, I'm not sure exactly how big the cost of additional division would be in practice. 3 seems slightly overkill, and I don't have a really good idea at the moment. Based on these thoughts, my instincts tell me to go with 1. |
I agree. I also see
I don't see why we cannot change nanotime to use
and it seems to be working fine.
I would not use
I would (if I had free time) try 2 or 3 first. Maybe division is not expensive enough? Can we do division in every 100's nanotime call to adjust for the drift? Making runtime.nanotime and time.Now more precise might be beneficial in other areas (not just for benchmarks). I am also worried about creating too many functions that read time. They all use different approach to collect time. How do you know the time they return is all in sync? And different implementations might diverge. Alex |
As far as I recall QPC is unreliable for measuring long periods of times. Best reference mentioning issues I was able to find https://stackoverflow.com/a/5297163/192220. More in depth info on timing issues https://github.com/chromium/chromium/blob/08dbb44e81454b6d67c3b6f4989e7e58e88f4b0b/base/time/time_win.cc#L14. MSDN also only suggests it for measuring short periods of time https://docs.microsoft.com/en-us/windows/desktop/SysInfo/acquiring-high-resolution-time-stamps.
Yeah, I wouldn't use that value either. This is to demonstrate the make the issue more obvious. |
None of this looks authoritative enough for me. In fact, Microsoft suggests to use QPC for high resolution timers pretty much unconditionally https://docs.microsoft.com/en-us/windows/desktop/winmsg/about-timers https://docs.microsoft.com/en-us/windows/desktop/SysInfo/acquiring-high-resolution-time-stamps Also, given #31528, we will, probably, change nanotime implementation anyway. Maybe it is good time to address your issue and #31528 together? In particular, see my suggestion about QueryUnbiasedInterruptTimePrecise in #31528 (comment) ? In particular, if QueryUnbiasedInterruptTimePrecise is too slow / expensive to call from nanotime, maybe we could call it only from time.now, and call QueryUnbiasedInterruptTime from nanotime? Would that make Windows benchmarks resolution higher (I did not look at benchmarking code) ? Thank you/ Alex |
@alexbrainman Yes, changing nanotime would fix this issue. The fix would definitely be better overall, but as I said, it is somewhat scary to me. Then again, maybe the unreliability situation has improved significantly. |
My feeling exactly. Things change. Do not forget QueryUnbiasedInterruptTimePrecise is only available on Windows 10. But I will take that. Anyway, we have to come up with a solution for #31528, so lets wait for that before deciding what to do here. Alex |
Please don't use QueryUnbiasedInterruptTimePrecise, per #31528 (comment) |
The #31528 was closed with a different solution. I updated testing to use QueryPerformanceCounter in https://go-review.googlesource.com/c/go/+/227499, but I'm not sure whether this is the best way to go about it. Other ideas how to make benchmarking less noisy on quick runs would helpful. |
Change https://golang.org/cl/227499 mentions this issue: |
I spent some time investigating this. And, I agree, if we use QueryPerformanceCounter, we could improve our time.Duration precision from 1 millisecond to around few microsecond. Same with either QueryInterruptTimePrecise or QueryUnbiasedInterruptTimePrecise. But using syscall.Syscall to implement this code (similar to your CL 227499) is 10 times slower than current time.Now implementation. This is what I see
I don't think it is acceptable for time.Now. Maybe it is acceptable for testing package benchmark code. I am not sure. Unrelated to this. Austin tried replacing our current time.Now implementation with asm version of QueryUnbiasedInterruptTime (see https://go-review.googlesource.com/c/go/+/211307 ) - and it is fast enough replacement. Maybe we could do something similar for *Precise version - if only for time.Now implementation, not runtime.nanotime implementation. Alex |
Based on https://github.com/golang/go/wiki/MinimumRequirements#windows, the minimum required is Windows 2008R2. With regards to using I also agree that the performance of QPC (and similar) with syscall is not suitable for |
Change https://go.dev/cl/557315 mentions this issue: |
I'm fine with reverting the CL to avoid blocking other work, but I don't think that's the underlying issue. If there's no immediate fix, then we can revert to get things building again. Anyways, let's continue the discussion in #67077. |
I agree. Let's wait for others before we create a revert. We cannot submit the revert anyways without Googlers.
SGTM. Alex |
Change https://go.dev/cl/582135 mentions this issue: |
time.Since has optimizations for measuring monotonic time. For #31160. Change-Id: I0529b9f69b9f008e3414b8e386b6faa64af4a008 Reviewed-on: https://go-review.googlesource.com/c/go/+/582135 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
time.Now
has a large resolution on Windows, so the benchmark results end up with a timing error.As a demonstration here's code that measures
QueryPerformanceCounter
vs.time.Now
: https://play.golang.org/p/FN4AtJ9b51m.Which roughly says that my getting measurements at
1000000ns
or1ms
granularity.Fixing nanotime would be problematic (as seen in #8687), however benchmarks could use QueryPerformanceCounter instead.
The text was updated successfully, but these errors were encountered: