use renew_frame::{FrameLoop, FrameStats, FrameTiming, Nanos, StepBudget, Timestamp, Timestep};
use renew_memory::counters::quiet_window;
use renew_memory::{CountingAllocator, counters};
#[global_allocator]
static ALLOCATOR: CountingAllocator = CountingAllocator;
const DT: u64 = 16_666_667;
fn frame_body(
frame: &mut FrameLoop,
stats: &mut FrameStats,
timing: &mut FrameTiming,
sink: &mut u64,
now: u64,
) {
let plan = frame.begin_frame(Timestamp::from_nanos(now));
for step in plan.steps() {
*sink = sink
.wrapping_add(step.tick)
.wrapping_add(step.sim_time.get());
}
*sink = sink
.wrapping_add(plan.remainder().get())
.wrapping_add(plan.timestep().nanos().get());
stats.absorb(&plan);
timing.record(Nanos::from_nanos(now % 4_000_000), plan.step_count() > 0);
}
#[test]
#[cfg_attr(
feature = "sanitized",
ignore = "allocation counting is invalid under instrumented allocators"
)]
fn the_frame_schedule_allocates_exactly_nothing() {
let mut frame = FrameLoop::new(
Timestep::HZ_60,
StepBudget::DEFAULT,
Timestamp::from_nanos(0),
);
let mut stats = FrameStats::new();
let mut timing = FrameTiming::new();
let mut sink = 0u64;
let mut now = 0u64;
for delta in [DT, 200_000_000, 0] {
now += delta;
frame_body(&mut frame, &mut stats, &mut timing, &mut sink, now);
}
frame.resync(Timestamp::from_nanos(now));
quiet_window(5, || {
for _ in 0..64 {
for delta in [DT, DT / 2, DT / 2, 200_000_000, 0] {
now += delta;
frame_body(&mut frame, &mut stats, &mut timing, &mut sink, now);
}
frame_body(
&mut frame,
&mut stats,
&mut timing,
&mut sink,
now - 5_000_000,
);
frame.resync(Timestamp::from_nanos(now));
}
})
.expect("planning, stepping and tallying stay heap-silent");
assert!(stats.frames() >= 64 * 6);
assert!(stats.ticks() > 0);
assert!(stats.steps_dropped() > 0, "the budget never engaged");
assert_ne!(sink, 0);
let before = counters::snapshot();
let json = format!("{} {}", stats.json(), timing.json());
assert!(json.contains("\"schedule_hash\":\"0x"));
assert!(
counters::snapshot().allocations > before.allocations,
"the JSON adapters are expected to allocate; only the frame path is not"
);
}