wgengine/bench: improved rate selection.

The old decay-based one took a while to converge. This new one (based
very loosely on TCP BBR) seems to converge quickly on what seems to be
the best speed.

Signed-off-by: Avery Pennarun <apenwarr@tailscale.com>
pull/1583/head
Avery Pennarun 3 years ago
parent a92b9647c5
commit a7fe1d7c46

@ -90,7 +90,7 @@ func main() {
traf.Start(Addr1.IP, Addr2.IP, PayloadSize+ICMPMinSize, 0)
var cur, prev Snapshot
var pps float64
var pps int64
i := 0
for {
i += 1
@ -104,7 +104,7 @@ func main() {
if prev.WhenNsec == 0 {
logf("tx=%-6d rx=%-6d", d.TxPackets, d.RxPackets)
} else {
logf("%v @%7.0f pkt/sec", d, pps)
logf("%v @%7d pkt/s", d, pps)
}
}

@ -81,7 +81,7 @@ func runOnce(b *testing.B, setup SetupFunc, payload int) {
traf.Start(Addr1.IP, Addr2.IP, payload, int64(b.N))
var cur, prev Snapshot
var pps float64
var pps int64
i := 0
for traf.Running() {
i += 1
@ -93,7 +93,7 @@ func runOnce(b *testing.B, setup SetupFunc, payload int) {
d := cur.Sub(prev)
if prev.WhenNsec != 0 {
logf("%v @%7.0f pkt/sec", d, pps)
logf("%v @%7d pkt/sec", d, pps)
}
}

@ -74,9 +74,9 @@ type TrafficGen struct {
// caller wants to go.
nsPerPacket int64
// bestPPS is the "best observed packets-per-second" in recent
// memory.
bestPPS float64
// ppsHistory is the observed packets-per-second from recent
// samples.
ppsHistory [5]int64
}
// NewTrafficGen creates a new, initially locked, TrafficGen.
@ -221,28 +221,42 @@ func (t *TrafficGen) GotPacket(b []byte, ofs int) {
// 1% to receive them, leading to a misleading throughput calculation.
//
// Call this function multiple times per second.
func (t *TrafficGen) Adjust() (pps float64) {
func (t *TrafficGen) Adjust() (pps int64) {
t.mu.Lock()
defer t.mu.Unlock()
d := t.cur.Sub(t.prev)
// don't adjust rate until the first full period *after* receiving
// the first packet. This skips any handshake time in the underlying
// transport.
if t.prev.LastSeqRx == 0 {
if t.prev.LastSeqRx == 0 || d.DurationNsec == 0 {
t.prev = t.cur
return 0 // no estimate yet, continue at max speed
}
d := t.cur.Sub(t.prev)
t.bestPPS *= 0.97
pps = float64(d.RxPackets) * 1e9 / float64(d.DurationNsec)
if pps > 0 && t.prev.WhenNsec > 0 {
if pps > t.bestPPS {
t.bestPPS = pps
pps = int64(d.RxPackets) * 1e9 / int64(d.DurationNsec)
// We use a rate selection algorithm based loosely on TCP BBR.
// Basically, we set the transmit rate to be a bit higher than
// the best observed transmit rate in the last several time
// periods. This guarantees some packet loss, but should converge
// quickly on a rate near the sustainable maximum.
bestPPS := pps
for _, p := range t.ppsHistory {
if p > bestPPS {
bestPPS = p
}
t.nsPerPacket = int64(1e9 / t.bestPPS)
}
if pps > 0 && t.prev.WhenNsec > 0 {
copy(t.ppsHistory[1:], t.ppsHistory[0:len(t.ppsHistory)-1])
t.ppsHistory[0] = pps
}
if bestPPS > 0 {
pps = bestPPS * 103 / 100
t.nsPerPacket = int64(1e9 / pps)
}
t.prev = t.cur
return t.bestPPS
return pps
}

Loading…
Cancel
Save