diff --git a/internal/ackhandler/sent_packet_handler.go b/internal/ackhandler/sent_packet_handler.go index 72911e13..73bbff6a 100644 --- a/internal/ackhandler/sent_packet_handler.go +++ b/internal/ackhandler/sent_packet_handler.go @@ -17,7 +17,6 @@ const ( // In fraction of an RTT. timeReorderingFraction = 1.0 / 8 // The default RTT used before an RTT sample is taken. - // Note: This constant is also defined in the congestion package. defaultInitialRTT = 100 * time.Millisecond // defaultRTOTimeout is the RTO time on new connections defaultRTOTimeout = 500 * time.Millisecond diff --git a/internal/congestion/rtt_stats.go b/internal/congestion/rtt_stats.go index 599e350f..539410dd 100644 --- a/internal/congestion/rtt_stats.go +++ b/internal/congestion/rtt_stats.go @@ -7,50 +7,25 @@ import ( ) const ( - // Note: This constant is also defined in the ackhandler package. - initialRTTus = 100 * 1000 rttAlpha float32 = 0.125 oneMinusAlpha float32 = (1 - rttAlpha) rttBeta float32 = 0.25 oneMinusBeta float32 = (1 - rttBeta) - halfWindow float32 = 0.5 - quarterWindow float32 = 0.25 ) -type rttSample struct { - rtt time.Duration - time time.Time -} - // RTTStats provides round-trip statistics type RTTStats struct { - initialRTTus int64 - - recentMinRTTwindow time.Duration - minRTT time.Duration - latestRTT time.Duration - smoothedRTT time.Duration - meanDeviation time.Duration - - numMinRTTsamplesRemaining uint32 - - newMinRTT rttSample - recentMinRTT rttSample - halfWindowRTT rttSample - quarterWindowRTT rttSample + minRTT time.Duration + latestRTT time.Duration + smoothedRTT time.Duration + meanDeviation time.Duration } // NewRTTStats makes a properly initialized RTTStats object func NewRTTStats() *RTTStats { - return &RTTStats{ - initialRTTus: initialRTTus, - recentMinRTTwindow: utils.InfDuration, - } + return &RTTStats{} } -// InitialRTTus is the initial RTT in us -func (r *RTTStats) InitialRTTus() int64 { return r.initialRTTus } - // MinRTT Returns the minRTT for the entire connection. // May return Zero if no valid updates have occurred. func (r *RTTStats) MinRTT() time.Duration { return r.minRTT } @@ -59,28 +34,13 @@ func (r *RTTStats) MinRTT() time.Duration { return r.minRTT } // May return Zero if no valid updates have occurred. func (r *RTTStats) LatestRTT() time.Duration { return r.latestRTT } -// RecentMinRTT the minRTT since SampleNewRecentMinRtt has been called, or the -// minRTT for the entire connection if SampleNewMinRtt was never called. -func (r *RTTStats) RecentMinRTT() time.Duration { return r.recentMinRTT.rtt } - // SmoothedRTT returns the EWMA smoothed RTT for the connection. // May return Zero if no valid updates have occurred. func (r *RTTStats) SmoothedRTT() time.Duration { return r.smoothedRTT } -// GetQuarterWindowRTT gets the quarter window RTT -func (r *RTTStats) GetQuarterWindowRTT() time.Duration { return r.quarterWindowRTT.rtt } - -// GetHalfWindowRTT gets the half window RTT -func (r *RTTStats) GetHalfWindowRTT() time.Duration { return r.halfWindowRTT.rtt } - // MeanDeviation gets the mean deviation func (r *RTTStats) MeanDeviation() time.Duration { return r.meanDeviation } -// SetRecentMinRTTwindow sets how old a recent min rtt sample can be. -func (r *RTTStats) SetRecentMinRTTwindow(recentMinRTTwindow time.Duration) { - r.recentMinRTTwindow = recentMinRTTwindow -} - // UpdateRTT updates the RTT based on a new sample. func (r *RTTStats) UpdateRTT(sendDelta, ackDelay time.Duration, now time.Time) { if sendDelta == utils.InfDuration || sendDelta <= 0 { @@ -94,7 +54,6 @@ func (r *RTTStats) UpdateRTT(sendDelta, ackDelay time.Duration, now time.Time) { if r.minRTT == 0 || r.minRTT > sendDelta { r.minRTT = sendDelta } - r.updateRecentMinRTT(sendDelta, now) // Correct for ackDelay if information received from the peer results in a // an RTT sample at least as large as minRTT. Otherwise, only use the @@ -114,63 +73,12 @@ func (r *RTTStats) UpdateRTT(sendDelta, ackDelay time.Duration, now time.Time) { } } -func (r *RTTStats) updateRecentMinRTT(sample time.Duration, now time.Time) { // Recent minRTT update. - if r.numMinRTTsamplesRemaining > 0 { - r.numMinRTTsamplesRemaining-- - if r.newMinRTT.rtt == 0 || sample <= r.newMinRTT.rtt { - r.newMinRTT = rttSample{rtt: sample, time: now} - } - if r.numMinRTTsamplesRemaining == 0 { - r.recentMinRTT = r.newMinRTT - r.halfWindowRTT = r.newMinRTT - r.quarterWindowRTT = r.newMinRTT - } - } - - // Update the three recent rtt samples. - if r.recentMinRTT.rtt == 0 || sample <= r.recentMinRTT.rtt { - r.recentMinRTT = rttSample{rtt: sample, time: now} - r.halfWindowRTT = r.recentMinRTT - r.quarterWindowRTT = r.recentMinRTT - } else if sample <= r.halfWindowRTT.rtt { - r.halfWindowRTT = rttSample{rtt: sample, time: now} - r.quarterWindowRTT = r.halfWindowRTT - } else if sample <= r.quarterWindowRTT.rtt { - r.quarterWindowRTT = rttSample{rtt: sample, time: now} - } - - // Expire old min rtt samples. - if r.recentMinRTT.time.Before(now.Add(-r.recentMinRTTwindow)) { - r.recentMinRTT = r.halfWindowRTT - r.halfWindowRTT = r.quarterWindowRTT - r.quarterWindowRTT = rttSample{rtt: sample, time: now} - } else if r.halfWindowRTT.time.Before(now.Add(-time.Duration(float32(r.recentMinRTTwindow/time.Microsecond)*halfWindow) * time.Microsecond)) { - r.halfWindowRTT = r.quarterWindowRTT - r.quarterWindowRTT = rttSample{rtt: sample, time: now} - } else if r.quarterWindowRTT.time.Before(now.Add(-time.Duration(float32(r.recentMinRTTwindow/time.Microsecond)*quarterWindow) * time.Microsecond)) { - r.quarterWindowRTT = rttSample{rtt: sample, time: now} - } -} - -// SampleNewRecentMinRTT forces RttStats to sample a new recent min rtt within the next -// |numSamples| UpdateRTT calls. -func (r *RTTStats) SampleNewRecentMinRTT(numSamples uint32) { - r.numMinRTTsamplesRemaining = numSamples - r.newMinRTT = rttSample{} -} - // OnConnectionMigration is called when connection migrates and rtt measurement needs to be reset. func (r *RTTStats) OnConnectionMigration() { r.latestRTT = 0 r.minRTT = 0 r.smoothedRTT = 0 r.meanDeviation = 0 - r.initialRTTus = initialRTTus - r.numMinRTTsamplesRemaining = 0 - r.recentMinRTTwindow = utils.InfDuration - r.recentMinRTT = rttSample{} - r.halfWindowRTT = rttSample{} - r.quarterWindowRTT = rttSample{} } // ExpireSmoothedMetrics causes the smoothed_rtt to be increased to the latest_rtt if the latest_rtt diff --git a/internal/congestion/rtt_stats_test.go b/internal/congestion/rtt_stats_test.go index 76aaafa5..55c8ed18 100644 --- a/internal/congestion/rtt_stats_test.go +++ b/internal/congestion/rtt_stats_test.go @@ -18,7 +18,6 @@ var _ = Describe("RTT stats", func() { }) It("DefaultsBeforeUpdate", func() { - Expect(rttStats.InitialRTTus()).To(BeNumerically(">", 0)) Expect(rttStats.MinRTT()).To(Equal(time.Duration(0))) Expect(rttStats.SmoothedRTT()).To(Equal(time.Duration(0))) }) @@ -41,111 +40,23 @@ var _ = Describe("RTT stats", func() { It("MinRTT", func() { rttStats.UpdateRTT((200 * time.Millisecond), 0, time.Time{}) Expect(rttStats.MinRTT()).To(Equal((200 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((200 * time.Millisecond))) rttStats.UpdateRTT((10 * time.Millisecond), 0, time.Time{}.Add((10 * time.Millisecond))) Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((10 * time.Millisecond))) rttStats.UpdateRTT((50 * time.Millisecond), 0, time.Time{}.Add((20 * time.Millisecond))) Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((10 * time.Millisecond))) rttStats.UpdateRTT((50 * time.Millisecond), 0, time.Time{}.Add((30 * time.Millisecond))) Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((10 * time.Millisecond))) rttStats.UpdateRTT((50 * time.Millisecond), 0, time.Time{}.Add((40 * time.Millisecond))) Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((10 * time.Millisecond))) // Verify that ack_delay does not go into recording of MinRTT_. rttStats.UpdateRTT((7 * time.Millisecond), (2 * time.Millisecond), time.Time{}.Add((50 * time.Millisecond))) Expect(rttStats.MinRTT()).To(Equal((7 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((7 * time.Millisecond))) - }) - - It("RecentMinRTT", func() { - rttStats.UpdateRTT((10 * time.Millisecond), 0, time.Time{}) - Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((10 * time.Millisecond))) - - rttStats.SampleNewRecentMinRTT(4) - for i := 0; i < 3; i++ { - rttStats.UpdateRTT((50 * time.Millisecond), 0, time.Time{}) - Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((10 * time.Millisecond))) - } - rttStats.UpdateRTT((50 * time.Millisecond), - 0, time.Time{}) - Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((50 * time.Millisecond))) - }) - - It("WindowedRecentMinRTT", func() { - // Set the window to 99ms, so 25ms is more than a quarter rtt. - rttStats.SetRecentMinRTTwindow((99 * time.Millisecond)) - - now := time.Time{} - rttSample := (10 * time.Millisecond) - rttStats.UpdateRTT(rttSample, 0, now) - Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((10 * time.Millisecond))) - - // Gradually increase the rtt samples and ensure the RecentMinRTT starts - // rising. - for i := 0; i < 8; i++ { - now = now.Add((25 * time.Millisecond)) - rttSample += (10 * time.Millisecond) - rttStats.UpdateRTT(rttSample, 0, now) - Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.GetQuarterWindowRTT()).To(Equal(rttSample)) - Expect(rttStats.GetHalfWindowRTT()).To(Equal(rttSample - (10 * time.Millisecond))) - if i < 3 { - Expect(rttStats.RecentMinRTT()).To(Equal(10 * time.Millisecond)) - } else if i < 5 { - Expect(rttStats.RecentMinRTT()).To(Equal(30 * time.Millisecond)) - } else if i < 7 { - Expect(rttStats.RecentMinRTT()).To(Equal(50 * time.Millisecond)) - } else { - Expect(rttStats.RecentMinRTT()).To(Equal(70 * time.Millisecond)) - } - } - - // A new quarter rtt low sets that, but nothing else. - rttSample -= (5 * time.Millisecond) - rttStats.UpdateRTT(rttSample, 0, now) - Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.GetQuarterWindowRTT()).To(Equal(rttSample)) - Expect(rttStats.GetHalfWindowRTT()).To(Equal(rttSample - (5 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal((70 * time.Millisecond))) - - // A new half rtt low sets that and the quarter rtt low. - rttSample -= (15 * time.Millisecond) - rttStats.UpdateRTT(rttSample, 0, now) - Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.GetQuarterWindowRTT()).To(Equal(rttSample)) - Expect(rttStats.GetHalfWindowRTT()).To(Equal(rttSample)) - Expect(rttStats.RecentMinRTT()).To(Equal((70 * time.Millisecond))) - - // A new full window loss sets the RecentMinRTT, but not MinRTT. - rttSample = (65 * time.Millisecond) - rttStats.UpdateRTT(rttSample, 0, now) - Expect(rttStats.MinRTT()).To(Equal((10 * time.Millisecond))) - Expect(rttStats.GetQuarterWindowRTT()).To(Equal(rttSample)) - Expect(rttStats.GetHalfWindowRTT()).To(Equal(rttSample)) - Expect(rttStats.RecentMinRTT()).To(Equal(rttSample)) - - // A new all time low sets both the MinRTT and the RecentMinRTT. - rttSample = (5 * time.Millisecond) - rttStats.UpdateRTT(rttSample, 0, now) - - Expect(rttStats.MinRTT()).To(Equal(rttSample)) - Expect(rttStats.GetQuarterWindowRTT()).To(Equal(rttSample)) - Expect(rttStats.GetHalfWindowRTT()).To(Equal(rttSample)) - Expect(rttStats.RecentMinRTT()).To(Equal(rttSample)) }) It("ExpireSmoothedMetrics", func() { initialRtt := (10 * time.Millisecond) rttStats.UpdateRTT(initialRtt, 0, time.Time{}) Expect(rttStats.MinRTT()).To(Equal(initialRtt)) - Expect(rttStats.RecentMinRTT()).To(Equal(initialRtt)) Expect(rttStats.SmoothedRTT()).To(Equal(initialRtt)) Expect(rttStats.MeanDeviation()).To(Equal(initialRtt / 2)) @@ -175,7 +86,6 @@ var _ = Describe("RTT stats", func() { initialRtt := (10 * time.Millisecond) rttStats.UpdateRTT(initialRtt, 0, time.Time{}) Expect(rttStats.MinRTT()).To(Equal(initialRtt)) - Expect(rttStats.RecentMinRTT()).To(Equal(initialRtt)) Expect(rttStats.SmoothedRTT()).To(Equal(initialRtt)) badSendDeltas := []time.Duration{ @@ -191,7 +101,6 @@ var _ = Describe("RTT stats", func() { // EXPECT_CALL(log, Log(LOG_WARNING, _, _, _, HasSubstr("Ignoring"))); rttStats.UpdateRTT(badSendDelta, 0, time.Time{}) Expect(rttStats.MinRTT()).To(Equal(initialRtt)) - Expect(rttStats.RecentMinRTT()).To(Equal(initialRtt)) Expect(rttStats.SmoothedRTT()).To(Equal(initialRtt)) } }) @@ -205,14 +114,12 @@ var _ = Describe("RTT stats", func() { Expect(rttStats.LatestRTT()).To(Equal((200 * time.Millisecond))) Expect(rttStats.SmoothedRTT()).To(Equal((200 * time.Millisecond))) Expect(rttStats.MinRTT()).To(Equal((200 * time.Millisecond))) - Expect(rttStats.RecentMinRTT()).To(Equal(200 * time.Millisecond)) // Reset rtt stats on connection migrations. rttStats.OnConnectionMigration() Expect(rttStats.LatestRTT()).To(Equal(time.Duration(0))) Expect(rttStats.SmoothedRTT()).To(Equal(time.Duration(0))) Expect(rttStats.MinRTT()).To(Equal(time.Duration(0))) - Expect(rttStats.RecentMinRTT()).To(Equal(time.Duration(0))) }) })