refactor(client): use SignedDuration for effective RTT to support negative values
Simplify RttSample by merging signed and unsigned fields into a single SignedDuration for adjusted and effective RTT. This ensures accurate reporting and statistics when server processing time exceeds raw RTT.
This commit is contained in:
1 parent
37de7c96a1
commit
bec56d4114
14 files changed
+207
-86
No files matched your search
@@ -69,8 +69,8 @@ impl CoreStats {
|
||||
StatsEvent::UniqueReply {
|
||||
is_late, sample, ..
|
||||
} => self.apply_unique_reply(is_late, *sample),
|
||||
StatsEvent::DuplicateReply { .. } => {
|
||||
self.apply_duplicate_reply();
|
||||
StatsEvent::DuplicateReply { bytes, .. } => {
|
||||
self.apply_duplicate_reply(bytes);
|
||||
EventStatsUpdate::default()
|
||||
}
|
||||
StatsEvent::Loss { .. } => {
|
||||
@@ -81,8 +81,8 @@ impl CoreStats {
|
||||
self.apply_warning();
|
||||
EventStatsUpdate::default()
|
||||
}
|
||||
StatsEvent::UntrackedLate { .. } => {
|
||||
self.apply_untracked_late();
|
||||
StatsEvent::UntrackedLate { bytes, .. } => {
|
||||
self.apply_untracked_late(bytes);
|
||||
EventStatsUpdate::default()
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,12 @@ impl CoreStats {
|
||||
.saturating_add(sample.bytes as u64);
|
||||
|
||||
if let Some(count) = sample.received_count {
|
||||
self.packets.server_packets_received = Some(u64::from(count));
|
||||
let count = u64::from(count);
|
||||
self.packets.server_packets_received = Some(
|
||||
self.packets
|
||||
.server_packets_received
|
||||
.map_or(count, |current| current.max(count)),
|
||||
);
|
||||
}
|
||||
if let Some(window) = sample.received_window {
|
||||
self.packets.server_received_window = Some(window);
|
||||
@@ -181,10 +186,11 @@ impl CoreStats {
|
||||
updates
|
||||
}
|
||||
|
||||
fn apply_duplicate_reply(&mut self) {
|
||||
fn apply_duplicate_reply(&mut self, bytes: usize) {
|
||||
self.events.duplicate_replies += 1;
|
||||
self.packets.packets_received += 1;
|
||||
self.packets.duplicates += 1;
|
||||
self.packets.bytes_received = self.packets.bytes_received.saturating_add(bytes as u64);
|
||||
}
|
||||
|
||||
fn apply_loss(&mut self) {
|
||||
@@ -195,8 +201,11 @@ impl CoreStats {
|
||||
self.events.warning_events += 1;
|
||||
}
|
||||
|
||||
fn apply_untracked_late(&mut self) {
|
||||
fn apply_untracked_late(&mut self, bytes: usize) {
|
||||
self.events.untracked_late_replies += 1;
|
||||
self.packets.packets_received += 1;
|
||||
self.packets.late_packets += 1;
|
||||
self.packets.bytes_received = self.packets.bytes_received.saturating_add(bytes as u64);
|
||||
}
|
||||
|
||||
pub(crate) fn snapshot(&self) -> Snapshot {
|
||||
|
||||
@@ -198,6 +198,9 @@ pub struct EventCounts {
|
||||
/// Warning events processed.
|
||||
pub warning_events: u64,
|
||||
/// Late replies that could not be matched to retained in-flight state.
|
||||
///
|
||||
/// These replies are observed on the socket, but cannot contribute RTT,
|
||||
/// one-way delay, server-processing, or IPDV samples.
|
||||
pub untracked_late_replies: u64,
|
||||
}
|
||||
|
||||
@@ -206,19 +209,26 @@ pub struct EventCounts {
|
||||
pub struct PacketCounts {
|
||||
/// Probe packets sent by the local client.
|
||||
pub packets_sent: u64,
|
||||
/// Reply packets received by the local client, including duplicates and late packets.
|
||||
/// Reply packets observed by the local client.
|
||||
///
|
||||
/// This includes unique measurable replies, duplicate replies, and late
|
||||
/// replies that cannot be matched to retained in-flight state.
|
||||
pub packets_received: u64,
|
||||
/// Unique replies received by the local client.
|
||||
/// Unique replies that can contribute timing measurements.
|
||||
pub unique_replies: u64,
|
||||
/// Duplicate replies received by the local client.
|
||||
pub duplicates: u64,
|
||||
/// Late reply packets received by the local client.
|
||||
/// Late reply packets received by the local client, including untracked-late replies.
|
||||
pub late_packets: u64,
|
||||
/// Probe bytes sent by the local client.
|
||||
pub bytes_sent: u64,
|
||||
/// Reply bytes received by the local client.
|
||||
/// Reply bytes observed by the local client.
|
||||
///
|
||||
/// This includes bytes from unique measurable replies, duplicate replies,
|
||||
/// and untracked-late replies. Per-category byte counts are not currently
|
||||
/// exposed separately.
|
||||
pub bytes_received: u64,
|
||||
/// Server-reported packets received, when available.
|
||||
/// Highest cumulative server-reported packets received, when available.
|
||||
pub server_packets_received: Option<u64>,
|
||||
/// Server-reported receive window, when available.
|
||||
pub server_received_window: Option<u64>,
|
||||
|
||||
@@ -22,6 +22,7 @@ pub(crate) enum StatsEvent {
|
||||
},
|
||||
DuplicateReply {
|
||||
at: Instant,
|
||||
bytes: usize,
|
||||
},
|
||||
Loss {
|
||||
at: Instant,
|
||||
@@ -31,6 +32,7 @@ pub(crate) enum StatsEvent {
|
||||
},
|
||||
UntrackedLate {
|
||||
at: Instant,
|
||||
bytes: usize,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -96,11 +98,17 @@ pub(crate) fn normalize_event(event: &ClientEvent) -> Option<StatsEvent> {
|
||||
*bytes,
|
||||
)),
|
||||
}),
|
||||
ClientEvent::LateReply { received_at, .. } => Some(StatsEvent::UntrackedLate {
|
||||
ClientEvent::LateReply {
|
||||
received_at, bytes, ..
|
||||
} => Some(StatsEvent::UntrackedLate {
|
||||
at: received_at.mono,
|
||||
bytes: *bytes,
|
||||
}),
|
||||
ClientEvent::DuplicateReply { received_at, .. } => Some(StatsEvent::DuplicateReply {
|
||||
ClientEvent::DuplicateReply {
|
||||
received_at, bytes, ..
|
||||
} => Some(StatsEvent::DuplicateReply {
|
||||
at: received_at.mono,
|
||||
bytes: *bytes,
|
||||
}),
|
||||
ClientEvent::EchoLoss { timeout_at, .. } => Some(StatsEvent::Loss { at: *timeout_at }),
|
||||
ClientEvent::Warning { at, .. } => Some(StatsEvent::Warning { at: at.mono }),
|
||||
@@ -115,10 +123,10 @@ impl StatsEvent {
|
||||
match self {
|
||||
Self::Sent { at, .. }
|
||||
| Self::UniqueReply { at, .. }
|
||||
| Self::DuplicateReply { at }
|
||||
| Self::DuplicateReply { at, .. }
|
||||
| Self::Loss { at }
|
||||
| Self::Warning { at }
|
||||
| Self::UntrackedLate { at } => *at,
|
||||
| Self::UntrackedLate { at, .. } => *at,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,11 +156,11 @@ impl ReplySample {
|
||||
received_stats: Option<ReceivedStatsSample>,
|
||||
bytes: usize,
|
||||
) -> Self {
|
||||
let rtt_primary_ns = signed_duration_ns(rtt.effective_signed);
|
||||
let rtt_primary_ns = signed_duration_ns(rtt.effective);
|
||||
Self {
|
||||
bytes,
|
||||
rtt_raw_ns: duration_ns_i128(rtt.raw),
|
||||
rtt_adjusted_ns: rtt.adjusted_signed.map(signed_duration_ns),
|
||||
rtt_adjusted_ns: rtt.adjusted.map(signed_duration_ns),
|
||||
send_delay_ns: one_way
|
||||
.and_then(|sample| sample.client_to_server)
|
||||
.map(duration_ns_i128),
|
||||
|
||||
Reference in new issue
Block a user