From 21f7f01289577698eb70a4558d588bd00b6fed01 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 31 Oct 2018 15:07:57 +0100 Subject: [PATCH] runtime: avoid runtimeNano call on a common netpoll path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit runtimeNano is slower than nanotime, so pass the duration to runtime_pollSetDeadline as is. netpoll can add nanotime itself. Arguably a bit simpler because, say, a negative duration clearly represents already expired timer, no need to compare to nanotime again. This may also fix an obscure corner case when a deadline in past which happens to be nanotime 0 is confused with no deadline at all, which are radically different things. Also don't compute any durations and times if Time is zero (currently we first compute everything and then reset d back to 0, which is wasteful). name old time/op new time/op delta TCP4OneShotTimeout-6 17.1µs ± 0% 17.0µs ± 0% ~ (p=0.421 n=5+5) SetReadDeadline-6 230ns ± 0% 205ns ± 1% -10.63% (p=0.008 n=5+5) Change-Id: I2aad699270289a5b9ead68f5e44ec4ec6d96baa0 Reviewed-on: https://go-review.googlesource.com/c/146344 Reviewed-by: Ian Lance Taylor Run-TryBot: Dmitry Vyukov --- src/internal/poll/fd_poll_runtime.go | 15 ++++++--------- src/runtime/netpoll.go | 9 +++++++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/internal/poll/fd_poll_runtime.go b/src/internal/poll/fd_poll_runtime.go index a48e62eefa..f4540a60f6 100644 --- a/src/internal/poll/fd_poll_runtime.go +++ b/src/internal/poll/fd_poll_runtime.go @@ -136,15 +136,12 @@ func (fd *FD) SetWriteDeadline(t time.Time) error { } func setDeadlineImpl(fd *FD, t time.Time, mode int) error { - diff := int64(time.Until(t)) - d := runtimeNano() + diff - if d <= 0 && diff > 0 { - // If the user has a deadline in the future, but the delay calculation - // overflows, then set the deadline to the maximum possible value. - d = 1<<63 - 1 - } - if t.IsZero() { - d = 0 + var d int64 + if !t.IsZero() { + d = int64(time.Until(t)) + if d == 0 { + d = -1 // don't confuse deadline right now with no deadline + } } if err := fd.incref(); err != nil { return err diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go index f914844cdf..7e6e93d6c3 100644 --- a/src/runtime/netpoll.go +++ b/src/runtime/netpoll.go @@ -201,8 +201,13 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) { } rd0, wd0 := pd.rd, pd.wd combo0 := rd0 > 0 && rd0 == wd0 - if d != 0 && d <= nanotime() { - d = -1 + if d > 0 { + d += nanotime() + if d <= 0 { + // If the user has a deadline in the future, but the delay calculation + // overflows, then set the deadline to the maximum possible value. + d = 1<<63 - 1 + } } if mode == 'r' || mode == 'r'+'w' { pd.rd = d