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

Open
networkimprov opened this Issue Jan 13, 2019 · 11 comments

Comments

Projects
None yet
6 participants
@networkimprov
Copy link

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

This comment has been minimized.

Copy link
Member

commented Jan 13, 2019

@networkimprov how much better using SetWaitableTimer than 2ms?

Alex

@jordanrh1

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link
Member

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Author

commented Feb 15, 2019

This should be reopened...

@alexbrainman

This comment has been minimized.

Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.