forked from quic-go/quic-go
expose basic connection stats via Conn.ConnectionStats (#5281)
* Add ConnectionStats * remove for loop * Add comments * Update comments --------- Co-authored-by: Marco Munizaga <git@marcopolo.io>
This commit is contained in:
14
internal/utils/connstats.go
Normal file
14
internal/utils/connstats.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package utils
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// ConnectionStats stores stats for the connection. See the public
|
||||
// ConnectionStats struct in connection.go for more information
|
||||
type ConnectionStats struct {
|
||||
BytesSent atomic.Uint64
|
||||
PacketsSent atomic.Uint64
|
||||
BytesReceived atomic.Uint64
|
||||
PacketsReceived atomic.Uint64
|
||||
BytesLost atomic.Uint64
|
||||
PacketsLost atomic.Uint64
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
@@ -19,31 +20,41 @@ const (
|
||||
type RTTStats struct {
|
||||
hasMeasurement bool
|
||||
|
||||
minRTT time.Duration
|
||||
latestRTT time.Duration
|
||||
smoothedRTT time.Duration
|
||||
meanDeviation time.Duration
|
||||
minRTT atomic.Int64 // nanoseconds
|
||||
latestRTT atomic.Int64 // nanoseconds
|
||||
smoothedRTT atomic.Int64 // nanoseconds
|
||||
meanDeviation atomic.Int64 // nanoseconds
|
||||
|
||||
maxAckDelay time.Duration
|
||||
maxAckDelay atomic.Int64 // nanoseconds
|
||||
}
|
||||
|
||||
// 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 }
|
||||
func (r *RTTStats) MinRTT() time.Duration {
|
||||
return time.Duration(r.minRTT.Load())
|
||||
}
|
||||
|
||||
// LatestRTT returns the most recent rtt measurement.
|
||||
// May return Zero if no valid updates have occurred.
|
||||
func (r *RTTStats) LatestRTT() time.Duration { return r.latestRTT }
|
||||
func (r *RTTStats) LatestRTT() time.Duration {
|
||||
return time.Duration(r.latestRTT.Load())
|
||||
}
|
||||
|
||||
// SmoothedRTT returns the smoothed RTT for the connection.
|
||||
// May return Zero if no valid updates have occurred.
|
||||
func (r *RTTStats) SmoothedRTT() time.Duration { return r.smoothedRTT }
|
||||
func (r *RTTStats) SmoothedRTT() time.Duration {
|
||||
return time.Duration(r.smoothedRTT.Load())
|
||||
}
|
||||
|
||||
// MeanDeviation gets the mean deviation
|
||||
func (r *RTTStats) MeanDeviation() time.Duration { return r.meanDeviation }
|
||||
func (r *RTTStats) MeanDeviation() time.Duration {
|
||||
return time.Duration(r.meanDeviation.Load())
|
||||
}
|
||||
|
||||
// MaxAckDelay gets the max_ack_delay advertised by the peer
|
||||
func (r *RTTStats) MaxAckDelay() time.Duration { return r.maxAckDelay }
|
||||
func (r *RTTStats) MaxAckDelay() time.Duration {
|
||||
return time.Duration(r.maxAckDelay.Load())
|
||||
}
|
||||
|
||||
// PTO gets the probe timeout duration.
|
||||
func (r *RTTStats) PTO(includeMaxAckDelay bool) time.Duration {
|
||||
@@ -67,32 +78,37 @@ func (r *RTTStats) UpdateRTT(sendDelta, ackDelay time.Duration) {
|
||||
// ackDelay but the raw observed sendDelta, since poor clock granularity at
|
||||
// the client may cause a high ackDelay to result in underestimation of the
|
||||
// r.minRTT.
|
||||
if r.minRTT == 0 || r.minRTT > sendDelta {
|
||||
r.minRTT = sendDelta
|
||||
minRTT := time.Duration(r.minRTT.Load())
|
||||
if minRTT == 0 || minRTT > sendDelta {
|
||||
minRTT = sendDelta
|
||||
r.minRTT.Store(int64(sendDelta))
|
||||
}
|
||||
|
||||
// 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
|
||||
// sendDelta.
|
||||
sample := sendDelta
|
||||
if sample-r.minRTT >= ackDelay {
|
||||
if sample-minRTT >= ackDelay {
|
||||
sample -= ackDelay
|
||||
}
|
||||
r.latestRTT = sample
|
||||
r.latestRTT.Store(int64(sample))
|
||||
// First time call.
|
||||
if !r.hasMeasurement {
|
||||
r.hasMeasurement = true
|
||||
r.smoothedRTT = sample
|
||||
r.meanDeviation = sample / 2
|
||||
r.smoothedRTT.Store(int64(sample))
|
||||
r.meanDeviation.Store(int64(sample / 2))
|
||||
} else {
|
||||
r.meanDeviation = time.Duration(oneMinusBeta*float32(r.meanDeviation/time.Microsecond)+rttBeta*float32((r.smoothedRTT-sample).Abs()/time.Microsecond)) * time.Microsecond
|
||||
r.smoothedRTT = time.Duration((float32(r.smoothedRTT/time.Microsecond)*oneMinusAlpha)+(float32(sample/time.Microsecond)*rttAlpha)) * time.Microsecond
|
||||
smoothedRTT := r.SmoothedRTT()
|
||||
meanDev := time.Duration(oneMinusBeta*float32(r.MeanDeviation()/time.Microsecond)+rttBeta*float32((smoothedRTT-sample).Abs()/time.Microsecond)) * time.Microsecond
|
||||
newSmoothedRTT := time.Duration((float32(smoothedRTT/time.Microsecond)*oneMinusAlpha)+(float32(sample/time.Microsecond)*rttAlpha)) * time.Microsecond
|
||||
r.meanDeviation.Store(int64(meanDev))
|
||||
r.smoothedRTT.Store(int64(newSmoothedRTT))
|
||||
}
|
||||
}
|
||||
|
||||
// SetMaxAckDelay sets the max_ack_delay
|
||||
func (r *RTTStats) SetMaxAckDelay(mad time.Duration) {
|
||||
r.maxAckDelay = mad
|
||||
r.maxAckDelay.Store(int64(mad))
|
||||
}
|
||||
|
||||
// SetInitialRTT sets the initial RTT.
|
||||
@@ -105,15 +121,26 @@ func (r *RTTStats) SetInitialRTT(t time.Duration) {
|
||||
if r.hasMeasurement {
|
||||
return
|
||||
}
|
||||
r.smoothedRTT = t
|
||||
r.latestRTT = t
|
||||
r.smoothedRTT.Store(int64(t))
|
||||
r.latestRTT.Store(int64(t))
|
||||
}
|
||||
|
||||
func (r *RTTStats) ResetForPathMigration() {
|
||||
r.hasMeasurement = false
|
||||
r.minRTT = 0
|
||||
r.latestRTT = 0
|
||||
r.smoothedRTT = 0
|
||||
r.meanDeviation = 0
|
||||
r.minRTT.Store(0)
|
||||
r.latestRTT.Store(0)
|
||||
r.smoothedRTT.Store(0)
|
||||
r.meanDeviation.Store(0)
|
||||
// max_ack_delay remains valid
|
||||
}
|
||||
|
||||
func (r *RTTStats) Clone() *RTTStats {
|
||||
out := &RTTStats{}
|
||||
out.hasMeasurement = r.hasMeasurement
|
||||
out.minRTT.Store(r.minRTT.Load())
|
||||
out.latestRTT.Store(r.latestRTT.Load())
|
||||
out.smoothedRTT.Store(r.smoothedRTT.Load())
|
||||
out.meanDeviation.Store(r.meanDeviation.Load())
|
||||
out.maxAckDelay.Store(r.maxAckDelay.Load())
|
||||
return out
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user