Skip to content

Commit 9c12333

Browse files
fix latency calculation
1 parent 0c6ac6e commit 9c12333

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

src/speedtest.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ use reqwest::{blocking::Client, StatusCode};
1111
use serde::Serialize;
1212
use std::{
1313
fmt::Display,
14+
sync::atomic::{AtomicBool, Ordering},
1415
time::{Duration, Instant},
1516
};
1617

1718
const BASE_URL: &str = "https://speed.cloudflare.com";
1819
const DOWNLOAD_URL: &str = "__down?bytes=";
1920
const UPLOAD_URL: &str = "__up";
21+
static WARNED_NEGATIVE_LATENCY: AtomicBool = AtomicBool::new(false);
2022

2123
#[derive(Clone, Copy, Debug, Hash, Serialize, Eq, PartialEq)]
2224
pub enum TestType {
@@ -180,29 +182,37 @@ pub fn test_latency(client: &Client) -> f64 {
180182
let req_builder = client.get(url);
181183

182184
let start = Instant::now();
183-
let response = req_builder.send().expect("failed to get response");
185+
let mut response = req_builder.send().expect("failed to get response");
184186
let _status_code = response.status();
185-
let duration = start.elapsed().as_secs_f64() * 1_000.0;
187+
// Drain body to complete the request; ignore errors.
188+
let _ = std::io::copy(&mut response, &mut std::io::sink());
189+
let total_ms = start.elapsed().as_secs_f64() * 1_000.0;
186190

187191
let re = Regex::new(r"cfRequestDuration;dur=([\d.]+)").unwrap();
192+
let server_timing = response
193+
.headers()
194+
.get("Server-Timing")
195+
.expect("No Server-Timing in response header")
196+
.to_str()
197+
.unwrap();
188198
let cf_req_duration: f64 = re
189-
.captures(
190-
response
191-
.headers()
192-
.get("Server-Timing")
193-
.expect("No Server-Timing in response header")
194-
.to_str()
195-
.unwrap(),
196-
)
199+
.captures(server_timing)
197200
.unwrap()
198201
.get(1)
199202
.unwrap()
200203
.as_str()
201204
.parse()
202205
.unwrap();
203-
let mut req_latency = duration - cf_req_duration;
206+
let mut req_latency = total_ms - cf_req_duration;
207+
log::debug!(
208+
"latency debug: total_ms={total_ms:.3} cf_req_duration_ms={cf_req_duration:.3} req_latency_total={req_latency:.3} server_timing={server_timing}"
209+
);
204210
if req_latency < 0.0 {
205-
// TODO investigate negative latency values
211+
if !WARNED_NEGATIVE_LATENCY.swap(true, Ordering::Relaxed) {
212+
log::warn!(
213+
"negative latency after server timing subtraction; clamping to 0.0 (total_ms={total_ms:.3} cf_req_duration_ms={cf_req_duration:.3})"
214+
);
215+
}
206216
req_latency = 0.0
207217
}
208218
req_latency

0 commit comments

Comments
 (0)