Skip to content

Commit

Permalink
runtime: don't wake timeproc needlessly
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dvyukov committed Nov 2, 2018
1 parent 7f99845 commit a9280fa
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 5 deletions.
31 changes: 31 additions & 0 deletions src/net/tcpsock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
10 changes: 5 additions & 5 deletions src/runtime/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,18 +156,18 @@ 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)
}
if tb.rescheduling {
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
}
Expand Down

0 comments on commit a9280fa

Please sign in to comment.