mirror of
https://github.com/golang/go
synced 2024-11-08 09:36:24 -07:00
runtime: add and use modtimer in netpoll
Currently when netpoll deadline is incrementally prolonged, we delete and re-add timer each time. Add modtimer function that does both and use it when we need to modify an existing netpoll timer to avoid unnecessary lock/unlock. TCP4OneShotTimeout-6 17.2µs ± 0% 17.0µs ± 0% -0.82% (p=0.008 n=5+5) SetReadDeadline-6 274ns ± 2% 261ns ± 0% -4.89% (p=0.008 n=5+5) Update #25729 Change-Id: I08b89dbbc1785dd180e967a37b0aa23b0c4613a8 Reviewed-on: https://go-review.googlesource.com/c/146339 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
86d375498f
commit
a86f549703
@ -211,21 +211,13 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
|
||||
pd.wd = d
|
||||
}
|
||||
combo := pd.rd > 0 && pd.rd == pd.wd
|
||||
// Reset current timers if necessary.
|
||||
if pd.rt.f != nil && (pd.rd != rd0 || combo != combo0) {
|
||||
pd.rseq++ // invalidate current timers
|
||||
deltimer(&pd.rt)
|
||||
pd.rt.f = nil
|
||||
}
|
||||
if pd.wt.f != nil && (pd.wd != wd0 || combo != combo0) {
|
||||
pd.wseq++ // invalidate current timers
|
||||
deltimer(&pd.wt)
|
||||
pd.wt.f = nil
|
||||
}
|
||||
// Setup new timers.
|
||||
rtf := netpollReadDeadline
|
||||
if combo {
|
||||
if pd.rt.f == nil {
|
||||
pd.rt.f = netpollDeadline
|
||||
rtf = netpollDeadline
|
||||
}
|
||||
if pd.rt.f == nil {
|
||||
if pd.rd > 0 {
|
||||
pd.rt.f = rtf
|
||||
pd.rt.when = pd.rd
|
||||
// Copy current seq into the timer arg.
|
||||
// Timer func will check the seq against current descriptor seq,
|
||||
@ -234,21 +226,31 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
|
||||
pd.rt.seq = pd.rseq
|
||||
addtimer(&pd.rt)
|
||||
}
|
||||
} else {
|
||||
if pd.rd > 0 && pd.rt.f == nil {
|
||||
pd.rt.f = netpollReadDeadline
|
||||
pd.rt.when = pd.rd
|
||||
pd.rt.arg = pd
|
||||
pd.rt.seq = pd.rseq
|
||||
addtimer(&pd.rt)
|
||||
} else if pd.rd != rd0 || combo != combo0 {
|
||||
pd.rseq++ // invalidate current timers
|
||||
if pd.rd > 0 {
|
||||
modtimer(&pd.rt, pd.rd, 0, rtf, pd, pd.rseq)
|
||||
} else {
|
||||
deltimer(&pd.rt)
|
||||
pd.rt.f = nil
|
||||
}
|
||||
if pd.wd > 0 && pd.wt.f == nil {
|
||||
}
|
||||
if pd.wt.f == nil {
|
||||
if pd.wd > 0 && !combo {
|
||||
pd.wt.f = netpollWriteDeadline
|
||||
pd.wt.when = pd.wd
|
||||
pd.wt.arg = pd
|
||||
pd.wt.seq = pd.wseq
|
||||
addtimer(&pd.wt)
|
||||
}
|
||||
} else if pd.wd != wd0 || combo != combo0 {
|
||||
pd.wseq++ // invalidate current timers
|
||||
if pd.wd > 0 && !combo {
|
||||
modtimer(&pd.wt, pd.wd, 0, netpollWriteDeadline, pd, pd.wseq)
|
||||
} else {
|
||||
deltimer(&pd.wt)
|
||||
pd.wt.f = nil
|
||||
}
|
||||
}
|
||||
// If we set the new deadline in the past, unblock currently pending IO if any.
|
||||
var rg, wg *g
|
||||
|
@ -187,14 +187,22 @@ func deltimer(t *timer) bool {
|
||||
tb := t.tb
|
||||
|
||||
lock(&tb.lock)
|
||||
removed, ok := tb.deltimerLocked(t)
|
||||
unlock(&tb.lock)
|
||||
if !ok {
|
||||
badTimer()
|
||||
}
|
||||
return removed
|
||||
}
|
||||
|
||||
func (tb *timersBucket) deltimerLocked(t *timer) (removed, ok bool) {
|
||||
// t may not be registered anymore and may have
|
||||
// a bogus i (typically 0, if generated by Go).
|
||||
// Verify it before proceeding.
|
||||
i := t.i
|
||||
last := len(tb.t) - 1
|
||||
if i < 0 || i > last || tb.t[i] != t {
|
||||
unlock(&tb.lock)
|
||||
return false
|
||||
return false, true
|
||||
}
|
||||
if i != last {
|
||||
tb.t[i] = tb.t[last]
|
||||
@ -202,7 +210,7 @@ func deltimer(t *timer) bool {
|
||||
}
|
||||
tb.t[last] = nil
|
||||
tb.t = tb.t[:last]
|
||||
ok := true
|
||||
ok = true
|
||||
if i != last {
|
||||
if !siftupTimer(tb.t, i) {
|
||||
ok = false
|
||||
@ -211,11 +219,26 @@ func deltimer(t *timer) bool {
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
return true, ok
|
||||
}
|
||||
|
||||
func modtimer(t *timer, when, period int64, f func(interface{}, uintptr), arg interface{}, seq uintptr) {
|
||||
tb := t.tb
|
||||
|
||||
lock(&tb.lock)
|
||||
_, ok := tb.deltimerLocked(t)
|
||||
if ok {
|
||||
t.when = when
|
||||
t.period = period
|
||||
t.f = f
|
||||
t.arg = arg
|
||||
t.seq = seq
|
||||
ok = tb.addtimerLocked(t)
|
||||
}
|
||||
unlock(&tb.lock)
|
||||
if !ok {
|
||||
badTimer()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Timerproc runs the time-driven events.
|
||||
|
Loading…
Reference in New Issue
Block a user