#![cfg(not(miri))]
#![allow(clippy::std_instead_of_core, reason = "test code uses std")]
#![allow(clippy::unwrap_used, reason = "test code")]
#![allow(clippy::collection_is_never_read, reason = "tests retain Arc handles only to keep chunks alive")]
use alloc_tracker::{Allocator, Session};
use multitude::{Arc, Arena};
#[global_allocator]
static ALLOCATOR: Allocator<std::alloc::System> = Allocator::system();
const WORKLOAD: usize = 2_000;
const WARMUP_CYCLES: usize = 16;
fn quiet_session() -> Session {
Session::new().no_stdout().no_file()
}
#[test]
fn reset_reuses_chunks_without_reallocating() {
let mut arena = Arena::new();
let session = quiet_session();
let first = session.operation("first_fill");
{
let _span = first.measure_thread();
for i in 0..WORKLOAD {
let _v = arena.alloc(i as u64);
}
}
assert!(
first.total_bytes_allocated() > 0,
"first fill must allocate chunk(s) from the system"
);
arena.reset();
for _ in 0..WARMUP_CYCLES {
for i in 0..WORKLOAD {
let _v = arena.alloc(i as u64);
}
arena.reset();
}
let reused = session.operation("refill_after_reset");
{
let _span = reused.measure_thread();
for i in 0..WORKLOAD {
let _v = arena.alloc(i as u64);
}
}
assert_eq!(
reused.total_bytes_allocated(),
0,
"after warm-up, reset must reuse chunks rather than reallocate from the system"
);
}
#[test]
fn dropping_all_arcs_reclaims_chunks_for_reuse() {
let arena = Arena::new();
let session = quiet_session();
let mut hold: std::vec::Vec<Arc<u64>> = std::vec::Vec::with_capacity(WORKLOAD);
let first = session.operation("arc_first_fill");
{
let _span = first.measure_thread();
for i in 0..WORKLOAD {
hold.push(arena.alloc_arc(i as u64));
}
}
assert!(
first.total_bytes_allocated() > 0,
"allocating arcs must allocate chunk(s) from the system"
);
hold.clear();
for _ in 0..WARMUP_CYCLES {
for i in 0..WORKLOAD {
hold.push(arena.alloc_arc(i as u64));
}
hold.clear();
}
let reused = session.operation("arc_refill");
{
let _span = reused.measure_thread();
for i in 0..WORKLOAD {
hold.push(arena.alloc_arc(i as u64));
}
}
assert_eq!(
reused.total_bytes_allocated(),
0,
"after warm-up, re-allocating dropped arcs must reuse reclaimed chunks"
);
}
#[test]
fn steady_state_fill_and_drop_does_not_over_allocate() {
let arena = Arena::new();
let session = quiet_session();
let mut hold: std::vec::Vec<Arc<u64>> = std::vec::Vec::with_capacity(WORKLOAD);
for _ in 0..WARMUP_CYCLES {
for i in 0..WORKLOAD {
hold.push(arena.alloc_arc(i as u64));
}
hold.clear();
}
let steady = session.operation("steady_state");
{
let _span = steady.measure_thread();
for _round in 0..16 {
for i in 0..WORKLOAD {
hold.push(arena.alloc_arc(i as u64));
}
hold.clear();
}
}
assert_eq!(
steady.total_bytes_allocated(),
0,
"steady-state fill/drop cycles must reuse chunks, not over-allocate from the system"
);
}