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
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index 0e331b4..cacee62 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -138,12 +138,18 @@
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 0c96187..b829665 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -98,6 +98,15 @@
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 @@
* 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 46c77e3..638acd4 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -238,6 +238,7 @@
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;