Skip to content

Commit f9485d0

Browse files
karthiknadigCopilot
andcommitted
perf: count interpreter probe timeouts (#504)
Classify existing timeout warnings into privacy-safe categories in the E2E benchmark so the macOS cold tail can be tied to exact fallback probe counts without exposing paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e63cd2d commit f9485d0

1 file changed

Lines changed: 54 additions & 1 deletion

File tree

crates/pet/tests/e2e_performance.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,15 @@ impl PetClient {
401401
.join("\n")
402402
}
403403

404+
fn interpreter_probe_timeout_labels(&self) -> Vec<&'static str> {
405+
self.stderr_tail
406+
.lock()
407+
.expect("PET stderr tail mutex poisoned")
408+
.iter()
409+
.filter_map(|line| interpreter_probe_timeout_label(line))
410+
.collect()
411+
}
412+
404413
/// Configure the server
405414
pub fn configure(&mut self, config: Value) -> Result<Duration, String> {
406415
let start = Instant::now();
@@ -542,6 +551,39 @@ fn get_workspace_dir() -> PathBuf {
542551
})
543552
}
544553

554+
fn interpreter_probe_timeout_label(line: &str) -> Option<&'static str> {
555+
if !line.contains("Timed out after") || !line.contains("resolving Python via spawn") {
556+
return None;
557+
}
558+
if line.contains("/usr/bin/python3") {
559+
Some("usrBinPython3")
560+
} else if line.contains("CommandLineTools") {
561+
Some("commandLineTools")
562+
} else if line.contains("hostedtoolcache") {
563+
Some("hostedToolcache")
564+
} else if line.contains("/Library/Frameworks/Python.framework") {
565+
Some("pythonOrgFramework")
566+
} else if line.contains("/usr/local/bin") {
567+
Some("usrLocalBin")
568+
} else {
569+
Some("other")
570+
}
571+
}
572+
573+
#[test]
574+
fn interpreter_probe_timeouts_are_classified_without_exposing_paths() {
575+
assert_eq!(
576+
interpreter_probe_timeout_label(
577+
r#"Timed out after 15s resolving Python via spawn for "/usr/bin/python3"; killing child."#
578+
),
579+
Some("usrBinPython3")
580+
);
581+
assert_eq!(
582+
interpreter_probe_timeout_label("ordinary PET warning"),
583+
None
584+
);
585+
}
586+
545587
fn read_jsonrpc_message(reader: &mut impl BufRead) -> Result<Value, String> {
546588
let mut content_length = None;
547589
loop {
@@ -1212,6 +1254,7 @@ fn test_performance_summary() {
12121254
let mut time_to_first_env_stats = StatisticalMetrics::new();
12131255
let mut phase_stats = BTreeMap::new();
12141256
let mut locator_stats = BTreeMap::new();
1257+
let mut probe_timeout_counts: BTreeMap<String, usize> = BTreeMap::new();
12151258
let mut env_count = 0usize;
12161259
let mut manager_count = 0usize;
12171260

@@ -1254,6 +1297,15 @@ fn test_performance_summary() {
12541297
&mut phase_stats,
12551298
&mut locator_stats,
12561299
);
1300+
let timeout_labels = client.interpreter_probe_timeout_labels();
1301+
for label in &timeout_labels {
1302+
*probe_timeout_counts
1303+
.entry((*label).to_string())
1304+
.or_default() += 1;
1305+
}
1306+
if !timeout_labels.is_empty() {
1307+
println!(" Interpreter probe timeouts: {timeout_labels:?}");
1308+
}
12571309

12581310
println!(
12591311
" Iteration {}: startup={}ms, refresh={}ms, envs={}",
@@ -1315,7 +1367,8 @@ fn test_performance_summary() {
13151367
"time_to_first_env": time_to_first_env_stats.to_json()
13161368
},
13171369
"phases": phase_json,
1318-
"locators": locator_json
1370+
"locators": locator_json,
1371+
"interpreter_probe_timeouts": probe_timeout_counts
13191372
}))
13201373
.unwrap();
13211374

0 commit comments

Comments
 (0)