fix(stats): use age-based GC check to avoid evicting fresh metrics

The millis-since-base staleness check (last > now - 180s) saturated the
cutoff to 0 early in process life, so metrics stamped at 0ms failed the
strict > 0 test and were wrongly evicted by the immediate first GC
tick. Switch to age-based (now - last < 180s), equivalent to the
original Instant semantics and robust under clock saturation, which
fixes the flaky peer_conn_secure_mode_pubkey_and_encryption test.
This commit is contained in:
fanyang89
2026-06-26 23:31:34 +08:00
parent 1375cd1832
commit c12b73e1ae
+7 -2
View File
@@ -580,7 +580,12 @@ impl StatsManager {
// Drop metrics untouched for 180s and with no live handles. // Drop metrics untouched for 180s and with no live handles.
// Compare in the millis-since-base domain so neither the hot // Compare in the millis-since-base domain so neither the hot
// path nor GC reconstructs an `Instant` or locks. // path nor GC reconstructs an `Instant` or locks.
let cutoff_millis = now_millis().saturating_sub(180_000); //
// Use an age-based check (`now - last < STALE`) rather than
// `last > now - STALE`: early in process life `now_millis()` is
// tiny, so `now - STALE` saturates to 0 and a metric stamped at
// 0 would fail a strict `> 0` test and be wrongly evicted.
let now = now_millis();
let Some(counters) = counters_clone.upgrade() else { let Some(counters) = counters_clone.upgrade() else {
break; break;
@@ -588,7 +593,7 @@ impl StatsManager {
counters.retain(|_, metric_data: &mut Arc<MetricData>| { counters.retain(|_, metric_data: &mut Arc<MetricData>| {
Arc::strong_count(metric_data) > 1 Arc::strong_count(metric_data) > 1
|| metric_data.last_updated_millis() > cutoff_millis || now.saturating_sub(metric_data.last_updated_millis()) < 180_000
}); });
counters.shrink_to_fit(); counters.shrink_to_fit();
} }