feat(client): implement SignedDuration for precise RTT tracking
This commit is contained in:
4 files changed
+31
-4
No files matched your search
@@ -486,7 +486,7 @@ fn escape_value(value: &str) -> String {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use irtt_client::{ClientTimestamp, PacketMeta, RttSample};
|
use irtt_client::{ClientTimestamp, PacketMeta, RttSample, SignedDuration};
|
||||||
use irtt_proto::{Params, PROTOCOL_VERSION};
|
use irtt_proto::{Params, PROTOCOL_VERSION};
|
||||||
use std::{
|
use std::{
|
||||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
@@ -521,6 +521,8 @@ mod tests {
|
|||||||
raw: Duration::from_micros(1500),
|
raw: Duration::from_micros(1500),
|
||||||
adjusted: Some(Duration::from_micros(1200)),
|
adjusted: Some(Duration::from_micros(1200)),
|
||||||
effective: Duration::from_micros(1200),
|
effective: Duration::from_micros(1200),
|
||||||
|
adjusted_signed: Some(SignedDuration { ns: 1_200_000 }),
|
||||||
|
effective_signed: SignedDuration { ns: 1_200_000 },
|
||||||
},
|
},
|
||||||
server_timing: Some(ServerTiming {
|
server_timing: Some(ServerTiming {
|
||||||
receive_wall_ns: Some(1_000),
|
receive_wall_ns: Some(1_000),
|
||||||
|
|||||||
@@ -592,14 +592,26 @@ fn compute_rtt(
|
|||||||
let adjusted = server_processing.and_then(|sp| raw.checked_sub(sp));
|
let adjusted = server_processing.and_then(|sp| raw.checked_sub(sp));
|
||||||
|
|
||||||
let effective = adjusted.unwrap_or(raw);
|
let effective = adjusted.unwrap_or(raw);
|
||||||
|
let adjusted_signed = server_processing.map(|sp| SignedDuration {
|
||||||
|
ns: duration_ns_i128(raw) - duration_ns_i128(sp),
|
||||||
|
});
|
||||||
|
let effective_signed = adjusted_signed.unwrap_or(SignedDuration {
|
||||||
|
ns: duration_ns_i128(raw),
|
||||||
|
});
|
||||||
|
|
||||||
RttSample {
|
RttSample {
|
||||||
raw,
|
raw,
|
||||||
adjusted,
|
adjusted,
|
||||||
effective,
|
effective,
|
||||||
|
adjusted_signed,
|
||||||
|
effective_signed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn duration_ns_i128(duration: Duration) -> i128 {
|
||||||
|
i128::try_from(duration.as_nanos()).unwrap_or(i128::MAX)
|
||||||
|
}
|
||||||
|
|
||||||
fn compute_server_processing(ts: &TimestampFields) -> Option<Duration> {
|
fn compute_server_processing(ts: &TimestampFields) -> Option<Duration> {
|
||||||
if let (Some(recv_mono), Some(send_mono)) = (ts.recv_mono, ts.send_mono) {
|
if let (Some(recv_mono), Some(send_mono)) = (ts.recv_mono, ts.send_mono) {
|
||||||
let diff = send_mono.checked_sub(recv_mono)?;
|
let diff = send_mono.checked_sub(recv_mono)?;
|
||||||
@@ -1726,13 +1738,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn server_processing_greater_than_raw_does_not_underflow() {
|
fn server_processing_greater_than_raw_does_not_underflow() {
|
||||||
|
let base = Instant::now();
|
||||||
let rtt = compute_rtt(
|
let rtt = compute_rtt(
|
||||||
&ClientTimestamp {
|
&ClientTimestamp {
|
||||||
mono: Instant::now(),
|
mono: base,
|
||||||
wall: SystemTime::now(),
|
wall: SystemTime::now(),
|
||||||
},
|
},
|
||||||
&ClientTimestamp {
|
&ClientTimestamp {
|
||||||
mono: Instant::now() + Duration::from_nanos(1),
|
mono: base + Duration::from_nanos(1),
|
||||||
wall: SystemTime::now(),
|
wall: SystemTime::now(),
|
||||||
},
|
},
|
||||||
&TimestampFields {
|
&TimestampFields {
|
||||||
@@ -1743,6 +1756,11 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(rtt.adjusted.is_none());
|
assert!(rtt.adjusted.is_none());
|
||||||
assert_eq!(rtt.effective, rtt.raw);
|
assert_eq!(rtt.effective, rtt.raw);
|
||||||
|
assert_eq!(
|
||||||
|
rtt.adjusted_signed,
|
||||||
|
Some(SignedDuration { ns: -999_999_999 })
|
||||||
|
);
|
||||||
|
assert_eq!(rtt.effective_signed, SignedDuration { ns: -999_999_999 });
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -97,6 +97,13 @@ pub struct RttSample {
|
|||||||
pub raw: Duration,
|
pub raw: Duration,
|
||||||
pub adjusted: Option<Duration>,
|
pub adjusted: Option<Duration>,
|
||||||
pub effective: Duration,
|
pub effective: Duration,
|
||||||
|
pub adjusted_signed: Option<SignedDuration>,
|
||||||
|
pub effective_signed: SignedDuration,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct SignedDuration {
|
||||||
|
pub ns: i128,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ pub use config::{ClientConfig, NegotiationPolicy, RecvBudget, RunMode, SocketCon
|
|||||||
pub use error::{ClientError, EventSubscriptionError};
|
pub use error::{ClientError, EventSubscriptionError};
|
||||||
pub use event::{
|
pub use event::{
|
||||||
ClientEvent, OneWayDelaySample, OpenOutcome, PacketMeta, ReceivedStatsSample, RttSample,
|
ClientEvent, OneWayDelaySample, OpenOutcome, PacketMeta, ReceivedStatsSample, RttSample,
|
||||||
ServerTiming, WarningKind,
|
ServerTiming, SignedDuration, WarningKind,
|
||||||
};
|
};
|
||||||
pub use managed::{
|
pub use managed::{
|
||||||
CancellationToken, EventHub, EventSubscription, ManagedClient, ManagedClientSession,
|
CancellationToken, EventHub, EventSubscription, ManagedClient, ManagedClientSession,
|
||||||
|
|||||||
Reference in new issue
Block a user