Skip to content
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: NewTimer & NewTicker should use SetWaitableTimer on Windows #29714

Closed
networkimprov opened this issue Jan 13, 2019 · 12 comments
Closed

time: NewTimer & NewTicker should use SetWaitableTimer on Windows #29714

networkimprov opened this issue Jan 13, 2019 · 12 comments

Comments

@networkimprov
Copy link

@networkimprov networkimprov commented Jan 13, 2019

What version of Go are you using (go version)?

$ go version
go version go1.11.4 windows/amd64

Does this issue reproduce with the latest release?

Haven't tried 1.12beta

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
$ set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\admin\AppData\Local\go-build
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=C:\Users\admin\go
set GOPROXY=
set GORACE=
set GOROOT=C:\Go
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\admin\AppData\Local\Temp\go-build968081038=/tmp/go-build -gno-record-gcc-switches

What did you do?

Tested time.After with:
https://play.golang.org/p/TVDunzS8YU3

What did you expect to see?

100ns (repeating)

100ns is the result on Linux.

What did you see instead?

2.0014ms
1.9888ms
1.9951ms
1.9934ms
1.9945ms
1.9945ms
1.9951ms
1.9951ms
1.9945ms
1.9946ms

Discussion

SetWaitableTimer(), available since Win7, offers 100ns resolution. Go already calls it in the profiler.
https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-setwaitabletimerex

Windows hardware has shipped with a 10+MHz (100ns per click) interrupt timer for many years.
https://en.wikipedia.org/wiki/High_Precision_Event_Timer

Also applies to time.After, time.AfterFunc, and time.Tick.

Originally raised by @destinysync in #29485

CC: @jordanrh1 @alexbrainman @aclements

Thanks for your consideration!

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Jan 13, 2019

@networkimprov how much better using SetWaitableTimer than 2ms?

Alex

@jordanrh1
Copy link
Contributor

@jordanrh1 jordanrh1 commented Jan 14, 2019

2ms is a reasonable result. The smallest timer resolution you would see is about 1ms. Here is a doc with more info.

@networkimprov
Copy link
Author

@networkimprov networkimprov commented Jan 14, 2019

@jordanrh1 that doc doesn't discuss the 10MHz interrupt timer hardware described in the article I linked -- it only covers the older "clock interrupt". From the article:

An HPET chip consists of a 64-bit up-counter (main counter) counting at a frequency of at least 10 MHz, and a set of (at least three, up to 256) comparators. These comparators are 32- or 64-bit-wide. ... The HPET circuit in modern PCs is integrated into the southbridge chip.

Each comparator can generate an interrupt when the least significant bits are equal to the corresponding bits of the 64-bit main counter value. ... In one-shot mode the comparator fires an interrupt once when the main counter reaches the value stored in the comparator's register, while in the periodic mode the interrupts are generated at specified intervals.

@alexbrainman this hardware enables at least 100ns resolution; many common HPET chips are 14MHz.

@aclements
Copy link
Member

@aclements aclements commented Jan 14, 2019

SetWaitableTimer's argument has 100ns resolution, but I haven't seen anything on MSDN or elsewhere indicating that it actually operates at a resolution higher than the system clock resolution. Does anybody on this issue have evidence that it does?

@networkimprov
Copy link
Author

@networkimprov networkimprov commented Jan 14, 2019

The web is full of user reports on multimedia game performance differences after en/disabling the HPET in BIOS, tho that's not evidence of altered WaitableTimer resolution per se. I haven't seen anything explicit on how Windows surfaces HPET functionality, besides ACPI.

It seems the HPET must be manually enabled in BIOS and/or the OS on some systems.

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Jan 15, 2019

SetWaitableTimer's argument has 100ns resolution, but I haven't seen anything on MSDN or elsewhere indicating that it actually operates at a resolution higher than the system clock resolution. Does anybody on this issue have evidence that it does?

I do not think SetWaitableTimer will get us better resolution that we have now. But I am only guessing. I need to write little program to find out for sure.

My TODO list is very long at this moment, so I suspect others will beat me to it.

Alex

@aclements
Copy link
Member

@aclements aclements commented Jan 15, 2019

So far I haven't seen anything indicating that SetWaitableTimer has anything to do with the HPET. Yes, in theory it could use the HPET, but in theory so could all of the other time APIs we use on Windows.

If someone (maybe someone less busy than Alex :) wants to do the experiment to show whether SetWaitableTimer actually achieves higher resolution, that would be very interesting. Until then, I don't think there's anything to do on this issue.

@gopherbot
Copy link

@gopherbot gopherbot commented Feb 15, 2019

Timed out in state WaitingForInfo. Closing.

(I am just a bot, though. Please speak up if this is a mistake or you have the requested information.)

@gopherbot gopherbot closed this Feb 15, 2019
@networkimprov
Copy link
Author

@networkimprov networkimprov commented Feb 15, 2019

This should be reopened...

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Mar 20, 2019

I built this program https://play.golang.org/p/Vj39giJIRJX

and it prints

Slept for 10ms

on one of my computers.

@networkimprov I will let you play with my program and decide what to do here.

Alex

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Dec 13, 2019

As far as I can tell SetWaitableTimer permits a high precision in setting the timeout, but it still only fires on the system clock period. So this isn't going to be any better in practice than our current 1 millisecond timer resolution. So closing. Please comment if you have some reason to think that SetWaitableTimer can fire faster than the system clock.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants
You can’t perform that action at this time.