Skip to content
10 changes: 9 additions & 1 deletion crates/tracedecay-runtime-core/src/resident_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,14 @@ impl ResidentMemoryPressureV1 {
self.state()
}

/// Refresh pressure after reclaim without running reclaimers recursively.
fn resample_after_reclaim(&self) -> Option<ResidentMemoryPressureStateV1> {
let sample = (self.sampler)()?;
self.publish_observation(sample.admission_bytes());
self.publish_over_budget_gauge();
Some(self.state())
}

fn checkpoint_micros(&self) -> u64 {
u64::try_from(self.checkpoint_epoch.elapsed().as_micros()).unwrap_or(u64::MAX - 1)
}
Expand Down Expand Up @@ -1056,7 +1064,7 @@ pub fn register_process_allocator_pressure_reclaimer_v1(
Arc::new(move |request| {
let trim = release_process_allocator_memory_v1();
if let Some(pressure) = pressure_weak.upgrade() {
pressure.sample_for_checkpoint();
pressure.resample_after_reclaim();
}
tracing::info!(
event = "process_allocator_trimmed",
Expand Down
41 changes: 41 additions & 0 deletions crates/tracedecay-runtime-core/src/resident_memory/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,47 @@ fn allocator_trim_reclaimer_runs_under_pressure_and_reports_only_measured_releas
}
}

#[test]
fn allocator_trim_reclaimer_resamples_pressure_after_checkpoint_throttle() {
let limit = bytes(PRESSURE_TEST_LIMIT_BYTES);
let measured = Arc::new(AtomicU64::new(0));
let sampled = Arc::clone(&measured);
let pressure = Arc::new(ResidentMemoryPressureV1::with_sampler(
limit,
Arc::new(move || {
let observed = sampled.load(Ordering::Acquire);
Some(ProcessResidentSampleV1 {
resident_bytes: observed,
unreclaimable_bytes: observed,
swapped_bytes: 0,
cgroup_committed_bytes: None,
})
}),
));
let above_high = pressure.high_watermark_bytes() + 1;
let below_low = pressure.low_watermark_bytes().saturating_sub(1);
measured.store(above_high, Ordering::Release);
let _trim = super::register_process_allocator_pressure_reclaimer_v1(&pressure)
.expect("allocator trim registration");

assert!(pressure.sample_for_checkpoint().is_over_budget());
assert!(matches!(
pressure.state(),
ResidentMemoryPressureStateV1::OverBudget { .. }
));

measured.store(below_low, Ordering::Release);
pressure.publish_observed_resident_bytes(above_high);

assert!(matches!(
pressure.state(),
ResidentMemoryPressureStateV1::Nominal {
observed_bytes,
..
} if observed_bytes == below_low
));
}

#[test]
fn allocator_pressure_reclaimer_installation_preserves_registration_failure() {
let pressure = Arc::new(ResidentMemoryPressureV1::new(bytes(
Expand Down
Loading