time: speed up Since and Until

time.now is somewhat expensive (much more expensive than nanotime),
in the common case when Time has monotonic time we don't actually
need to call time.now in Since/Until as we can do calculation
based purely on monotonic times.

name                  old time/op  new time/op  delta
TCP4OneShotTimeout-6  17.0µs ± 0%  17.1µs ± 1%     ~     (p=0.151 n=5+5)
SetReadDeadline-6      261ns ± 0%   234ns ± 1%  -10.35%  (p=0.008 n=5+5)

Benchmark that only calls Until:

benchmark            old ns/op     new ns/op     delta
BenchmarkUntil       54.0          29.5          -45.37%

Update #25729

Change-Id: I5ac5af3eb1fe9f583cf79299f10b84501b1a0d7d
Reviewed-on: https://go-review.googlesource.com/c/146341
Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Dmitry Vyukov 2018-10-31 17:36:51 +01:00
parent a1ee0a21cf
commit fc3f8d43f1
1 changed files with 16 additions and 2 deletions

View File

@ -908,13 +908,27 @@ func (t Time) Sub(u Time) Duration {
// Since returns the time elapsed since t.
// It is shorthand for time.Now().Sub(t).
func Since(t Time) Duration {
return Now().Sub(t)
var now Time
if t.wall&hasMonotonic != 0 {
// Common case optimization: if t has monotomic time, then Sub will use only it.
now = Time{hasMonotonic, runtimeNano() - startNano, nil}
} else {
now = Now()
}
return now.Sub(t)
}
// Until returns the duration until t.
// It is shorthand for t.Sub(time.Now()).
func Until(t Time) Duration {
return t.Sub(Now())
var now Time
if t.wall&hasMonotonic != 0 {
// Common case optimization: if t has monotomic time, then Sub will use only it.
now = Time{hasMonotonic, runtimeNano() - startNano, nil}
} else {
now = Now()
}
return t.Sub(now)
}
// AddDate returns the time corresponding to adding the