]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: don't wake timeproc needlessly
authorDmitry Vyukov <dvyukov@google.com>
Wed, 31 Oct 2018 10:31:31 +0000 (11:31 +0100)
committerDmitry Vyukov <dvyukov@google.com>
Fri, 2 Nov 2018 12:48:03 +0000 (12:48 +0000)
It's not always necessary to wake timerproc even if we add
a new timer to the top of the heap. Since we don't wake and
reset timerproc when we remove timers, it still can be sleeping
with shorter timeout. It such case it's more profitable to let it
sleep and then update timeout when it wakes on its own rather than
proactively wake it, let it update timeout and go to sleep again.

name                  old time/op  new time/op  delta
TCP4OneShotTimeout-6  18.6µs ± 1%  17.2µs ± 0%   -7.66%  (p=0.008 n=5+5)
SetReadDeadline-6      562ns ± 5%   319ns ± 1%  -43.27%  (p=0.008 n=5+5)

Update #25729

Change-Id: Iec8eacb8563dbc574a82358b3bac7ac479c16826
Reviewed-on: https://go-review.googlesource.com/c/146337
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/net/tcpsock_test.go
src/runtime/time.go

index c2f26b1770765d53b61cfd471f7bf0a35dd97819..36d2ccb09a9b713393eba8183907fe0ac0fb92f7 100644 (file)
@@ -796,3 +796,34 @@ func TestCopyPipeIntoTCP(t *testing.T) {
                t.Fatal(err)
        }
 }
+
+func BenchmarkSetReadDeadline(b *testing.B) {
+       ln, err := newLocalListener("tcp")
+       if err != nil {
+               b.Fatal(err)
+       }
+       defer ln.Close()
+       var serv Conn
+       done := make(chan error)
+       go func() {
+               var err error
+               serv, err = ln.Accept()
+               done <- err
+       }()
+       c, err := Dial("tcp", ln.Addr().String())
+       if err != nil {
+               b.Fatal(err)
+       }
+       defer c.Close()
+       if err := <-done; err != nil {
+               b.Fatal(err)
+       }
+       defer serv.Close()
+       c.SetWriteDeadline(time.Now().Add(2 * time.Hour))
+       deadline := time.Now().Add(time.Hour)
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               c.SetReadDeadline(deadline)
+               deadline = deadline.Add(1)
+       }
+}
index 790819f25987f18384503e6e4701db908d483252..5e1a925dee6d858cea1b596aeca5692fd8af200f 100644 (file)
@@ -156,7 +156,7 @@ func (tb *timersBucket) addtimerLocked(t *timer) bool {
        }
        if t.i == 0 {
                // siftup moved to top: new earliest deadline.
-               if tb.sleeping {
+               if tb.sleeping && tb.sleepUntil > t.when {
                        tb.sleeping = false
                        notewakeup(&tb.waitnote)
                }
@@ -164,10 +164,10 @@ func (tb *timersBucket) addtimerLocked(t *timer) bool {
                        tb.rescheduling = false
                        goready(tb.gp, 0)
                }
-       }
-       if !tb.created {
-               tb.created = true
-               go timerproc(tb)
+               if !tb.created {
+                       tb.created = true
+                       go timerproc(tb)
+               }
        }
        return true
 }