From 2408301c987b832c4a8f0ce2ceda140043489a30 Mon Sep 17 00:00:00 2001 From: Toby Date: Sun, 14 Apr 2024 15:07:43 -0700 Subject: [PATCH] feat: pacer code improvements --- core/internal/congestion/common/pacer.go | 46 ++++++++---------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/core/internal/congestion/common/pacer.go b/core/internal/congestion/common/pacer.go index 4e089a3147..6adbd813c2 100644 --- a/core/internal/congestion/common/pacer.go +++ b/core/internal/congestion/common/pacer.go @@ -1,14 +1,14 @@ package common import ( - "math" "time" "github.com/apernet/quic-go/congestion" ) const ( - maxBurstPackets = 10 + maxBurstPackets = 10 + maxBurstPacingDelayMultiplier = 4 ) // Pacer implements a token bucket pacing algorithm. @@ -46,12 +46,12 @@ func (p *Pacer) Budget(now time.Time) congestion.ByteCount { if budget < 0 { // protect against overflows budget = congestion.ByteCount(1<<62 - 1) } - return minByteCount(p.maxBurstSize(), budget) + return min(p.maxBurstSize(), budget) } func (p *Pacer) maxBurstSize() congestion.ByteCount { - return maxByteCount( - congestion.ByteCount((congestion.MinPacingDelay+time.Millisecond).Nanoseconds())*p.getBandwidth()/1e9, + return max( + congestion.ByteCount((maxBurstPacingDelayMultiplier*congestion.MinPacingDelay).Nanoseconds())*p.getBandwidth()/1e9, maxBurstPackets*p.maxDatagramSize, ) } @@ -62,34 +62,18 @@ func (p *Pacer) TimeUntilSend() time.Time { if p.budgetAtLastSent >= p.maxDatagramSize { return time.Time{} } - return p.lastSentTime.Add(maxDuration( - congestion.MinPacingDelay, - time.Duration(math.Ceil(float64(p.maxDatagramSize-p.budgetAtLastSent)*1e9/ - float64(p.getBandwidth())))*time.Nanosecond, - )) + diff := 1e9 * uint64(p.maxDatagramSize-p.budgetAtLastSent) + bw := uint64(p.getBandwidth()) + // We might need to round up this value. + // Otherwise, we might have a budget (slightly) smaller than the datagram size when the timer expires. + d := diff / bw + // this is effectively a math.Ceil, but using only integer math + if diff%bw > 0 { + d++ + } + return p.lastSentTime.Add(max(congestion.MinPacingDelay, time.Duration(d)*time.Nanosecond)) } func (p *Pacer) SetMaxDatagramSize(s congestion.ByteCount) { p.maxDatagramSize = s } - -func maxByteCount(a, b congestion.ByteCount) congestion.ByteCount { - if a < b { - return b - } - return a -} - -func minByteCount(a, b congestion.ByteCount) congestion.ByteCount { - if a < b { - return a - } - return b -} - -func maxDuration(a, b time.Duration) time.Duration { - if a > b { - return a - } - return b -}