]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: do not do futile netpolls
authorDmitry Vyukov <dvyukov@google.com>
Wed, 11 Feb 2015 16:11:32 +0000 (19:11 +0300)
committerDmitry Vyukov <dvyukov@google.com>
Thu, 26 Feb 2015 11:03:07 +0000 (11:03 +0000)
There is no sense in trying to netpoll while there is
already a thread blocked in netpoll. And in most cases
there must be a thread blocked in netpoll, because
the first otherwise idle thread does blocking netpoll.

On some program I see that netpoll called from findrunnable
consumes 3% of time.

Change-Id: I0af1a73d637bffd9770ea50cb9278839716e8816
Reviewed-on: https://go-review.googlesource.com/4553
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Dmitry Vyukov <dvyukov@google.com>

src/runtime/proc1.go

index 7b0d7fd497168d3a8354b2bee6c4c0c05a5d7484..17be698c6729d8162a73a980cf4b38ba8c71c539 100644 (file)
@@ -1237,14 +1237,22 @@ top:
                }
        }
 
-       // poll network - returns list of goroutines
-       if gp := netpoll(false); gp != nil { // non-blocking
-               injectglist(gp.schedlink)
-               casgstatus(gp, _Gwaiting, _Grunnable)
-               if trace.enabled {
-                       traceGoUnpark(gp)
+       // Poll network.
+       // This netpoll is only an optimization before we resort to stealing.
+       // We can safely skip it if there a thread blocked in netpoll already.
+       // If there is any kind of logical race with that blocked thread
+       // (e.g. it has already returned from netpoll, but does not set lastpoll yet),
+       // this thread will do blocking netpoll below anyway.
+       if netpollinited() && sched.lastpoll != 0 {
+               if gp := netpoll(false); gp != nil { // non-blocking
+                       // netpoll returns list of goroutines linked by schedlink.
+                       injectglist(gp.schedlink)
+                       casgstatus(gp, _Gwaiting, _Grunnable)
+                       if trace.enabled {
+                               traceGoUnpark(gp)
+                       }
+                       return gp
                }
-               return gp
        }
 
        // If number of spinning M's >= number of busy P's, block.