From ea151041102692e52fbce353f12ca73bdc48cad7 Mon Sep 17 00:00:00 2001 From: Dmitriy Vyukov Date: Mon, 25 Mar 2013 20:57:36 +0400 Subject: [PATCH] net: band-aid for windows network poller Fixes performance of the current windows network poller with the new scheduler. Gives runtime a hint when GetQueuedCompletionStatus() will block. Fixes #5068. benchmark old ns/op new ns/op delta BenchmarkTCP4Persistent 4004000 33906 -99.15% BenchmarkTCP4Persistent-2 21790 17513 -19.63% BenchmarkTCP4Persistent-4 44760 34270 -23.44% BenchmarkTCP4Persistent-6 45280 43000 -5.04% R=golang-dev, alex.brainman, coocood, rsc CC=golang-dev https://golang.org/cl/7612045 --- src/pkg/net/fd_windows.go | 8 +++++++- src/pkg/runtime/cgocall.c | 15 ++++++++++++++- src/pkg/runtime/runtime.h | 1 + 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go index 0e331b44dc..cacee627b6 100644 --- a/src/pkg/net/fd_windows.go +++ b/src/pkg/net/fd_windows.go @@ -138,12 +138,18 @@ type resultSrv struct { iocp syscall.Handle } +func runtime_blockingSyscallHint() + func (s *resultSrv) Run() { var o *syscall.Overlapped var key uint32 var r ioResult for { - r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE) + r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, 0) + if r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil { + runtime_blockingSyscallHint() + r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE) + } switch { case r.err == nil: // Dequeued successfully completed IO packet. diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c index 0c96187495..b829665462 100644 --- a/src/pkg/runtime/cgocall.c +++ b/src/pkg/runtime/cgocall.c @@ -98,6 +98,15 @@ static void unwindm(void); static void endcgo(void); static FuncVal endcgoV = { endcgo }; +// Gives a hint that the next syscall +// executed by the current goroutine will block. +// Currently used only on windows. +void +net·runtime_blockingSyscallHint(void) +{ + g->blockingsyscall = true; +} + void runtime·cgocall(void (*fn)(void*), void *arg) { @@ -145,7 +154,11 @@ runtime·cgocall(void (*fn)(void*), void *arg) * so it is safe to call while "in a system call", outside * the $GOMAXPROCS accounting. */ - runtime·entersyscall(); + if(g->blockingsyscall) { + g->blockingsyscall = false; + runtime·entersyscallblock(); + } else + runtime·entersyscall(); runtime·asmcgocall(fn, arg); runtime·exitsyscall(); diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index 46c77e3fd5..638acd4740 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -238,6 +238,7 @@ struct G bool ispanic; bool issystem; // do not output in stack dump bool isbackground; // ignore in deadlock detector + bool blockingsyscall; // hint that the next syscall will block int8 raceignore; // ignore race detection events M* m; // for debuggers, but offset not hard-coded M* lockedm; -- 2.50.0