aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/syscall_windows_test.go
diff options
context:
space:
mode:
authorAlex Brainman <alex.brainman@gmail.com>2016-03-30 16:33:52 +1100
committerAlex Brainman <alex.brainman@gmail.com>2016-04-04 10:05:05 +0000
commit1f5b1b2b66ee530af8d86c190c74f49a2809ee92 (patch)
tree806859dd0db522ce7de71783fbe91a24460ad909 /src/runtime/syscall_windows_test.go
parent02adfa0b3d6dd46dc69709df7f39a1c947bec867 (diff)
downloadgo-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.go144
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)
+}