diff options
author | Alex Brainman <alex.brainman@gmail.com> | 2016-03-30 16:33:52 +1100 |
---|---|---|
committer | Alex Brainman <alex.brainman@gmail.com> | 2016-04-04 10:05:05 +0000 |
commit | 1f5b1b2b66ee530af8d86c190c74f49a2809ee92 (patch) | |
tree | 806859dd0db522ce7de71783fbe91a24460ad909 /src/runtime/syscall_windows_test.go | |
parent | 02adfa0b3d6dd46dc69709df7f39a1c947bec867 (diff) | |
download | go-1f5b1b2b66ee530af8d86c190c74f49a2809ee92.tar.gz go-1f5b1b2b66ee530af8d86c190c74f49a2809ee92.zip |
runtime: change osyield to use Windows SwitchToThread
It appears that windows osyield is just 15ms sleep on my computer
(see benchmarks below). Replace NtWaitForSingleObject in osyield
with SwitchToThread (as suggested by Dmitry).
Also add issue #14790 related benchmarks, so we can track perfomance
changes in CL 20834 and CL 20835 and beyond.
Update #14790
benchmark old ns/op new ns/op delta
BenchmarkChanToSyscallPing1ms 1953200 1953000 -0.01%
BenchmarkChanToSyscallPing15ms 31562904 31248400 -1.00%
BenchmarkSyscallToSyscallPing1ms 5247 4202 -19.92%
BenchmarkSyscallToSyscallPing15ms 5260 4374 -16.84%
BenchmarkChanToChanPing1ms 474 494 +4.22%
BenchmarkChanToChanPing15ms 468 489 +4.49%
BenchmarkOsYield1ms 980018 75.5 -99.99%
BenchmarkOsYield15ms 15625200 75.8 -100.00%
Change-Id: I1b4cc7caca784e2548ee3c846ca07ef152ebedce
Reviewed-on: https://go-review.googlesource.com/21294
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/runtime/syscall_windows_test.go')
-rw-r--r-- | src/runtime/syscall_windows_test.go | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index e069eec64c..730b6d6d9c 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -864,3 +864,147 @@ func TestLoadLibraryEx(t *testing.T) { t.Skipf("LoadLibraryEx not usable, but not expected. (LoadLibraryEx=%v; flags=%v)", have, flags) } + +var ( + modwinmm = syscall.NewLazyDLL("winmm.dll") + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + + proctimeBeginPeriod = modwinmm.NewProc("timeBeginPeriod") + proctimeEndPeriod = modwinmm.NewProc("timeEndPeriod") + + procCreateEvent = modkernel32.NewProc("CreateEventW") + procSetEvent = modkernel32.NewProc("SetEvent") +) + +func timeBeginPeriod(period uint32) { + syscall.Syscall(proctimeBeginPeriod.Addr(), 1, uintptr(period), 0, 0) +} + +func timeEndPeriod(period uint32) { + syscall.Syscall(proctimeEndPeriod.Addr(), 1, uintptr(period), 0, 0) +} + +func createEvent() (syscall.Handle, error) { + r0, _, e0 := syscall.Syscall6(procCreateEvent.Addr(), 4, 0, 0, 0, 0, 0, 0) + if r0 == 0 { + return 0, syscall.Errno(e0) + } + return syscall.Handle(r0), nil +} + +func setEvent(h syscall.Handle) error { + r0, _, e0 := syscall.Syscall(procSetEvent.Addr(), 1, uintptr(h), 0, 0) + if r0 == 0 { + return syscall.Errno(e0) + } + return nil +} + +func benchChanToSyscallPing(b *testing.B) { + ch := make(chan int) + event, err := createEvent() + if err != nil { + b.Fatal(err) + } + go func() { + for i := 0; i < b.N; i++ { + syscall.WaitForSingleObject(event, syscall.INFINITE) + ch <- 1 + } + }() + for i := 0; i < b.N; i++ { + err := setEvent(event) + if err != nil { + b.Fatal(err) + } + <-ch + } +} + +func BenchmarkChanToSyscallPing1ms(b *testing.B) { + timeBeginPeriod(1) + benchChanToSyscallPing(b) + timeEndPeriod(1) +} + +func BenchmarkChanToSyscallPing15ms(b *testing.B) { + benchChanToSyscallPing(b) +} + +func benchSyscallToSyscallPing(b *testing.B) { + event1, err := createEvent() + if err != nil { + b.Fatal(err) + } + event2, err := createEvent() + if err != nil { + b.Fatal(err) + } + go func() { + for i := 0; i < b.N; i++ { + syscall.WaitForSingleObject(event1, syscall.INFINITE) + err := setEvent(event2) + if err != nil { + b.Fatal(err) + } + } + }() + for i := 0; i < b.N; i++ { + err := setEvent(event1) + if err != nil { + b.Fatal(err) + } + syscall.WaitForSingleObject(event2, syscall.INFINITE) + } +} + +func BenchmarkSyscallToSyscallPing1ms(b *testing.B) { + timeBeginPeriod(1) + benchSyscallToSyscallPing(b) + timeEndPeriod(1) +} + +func BenchmarkSyscallToSyscallPing15ms(b *testing.B) { + benchSyscallToSyscallPing(b) +} + +func benchChanToChanPing(b *testing.B) { + ch1 := make(chan int) + ch2 := make(chan int) + go func() { + for i := 0; i < b.N; i++ { + <-ch1 + ch2 <- 1 + } + }() + for i := 0; i < b.N; i++ { + ch1 <- 1 + <-ch2 + } +} + +func BenchmarkChanToChanPing1ms(b *testing.B) { + timeBeginPeriod(1) + benchChanToChanPing(b) + timeEndPeriod(1) +} + +func BenchmarkChanToChanPing15ms(b *testing.B) { + benchChanToChanPing(b) +} + +func benchOsYield(b *testing.B) { + for i := 0; i < b.N; i++ { + runtime.OsYield() + } +} + +func BenchmarkOsYield1ms(b *testing.B) { + timeBeginPeriod(1) + benchOsYield(b) + timeEndPeriod(1) +} + +func BenchmarkOsYield15ms(b *testing.B) { + benchOsYield(b) +} |