pub(crate) mod alloc_budget;
pub(crate) mod extraction;
pub(crate) mod transforms;
use std::time::Instant;
use crate::blob::BlobData;
use crate::ecs::{Arena, ComponentStorage, FrameContext, PipelineContext, Resources};
use crate::gfx::profile::FrameProfile;
const TARGET_NS: u128 = 200_000_000;
const MAX_ITERS: u64 = 1 << 20;
pub(crate) struct BenchWorld {
pub components: ComponentStorage,
blob: BlobData,
profile: FrameProfile,
resources: Resources,
scratch: Arena,
}
impl BenchWorld {
pub(crate) fn new() -> BenchWorld {
BenchWorld {
components: ComponentStorage::default(),
blob: BlobData::empty(),
profile: FrameProfile::default(),
resources: Resources::default(),
scratch: Arena::with_capacity(1 << 20),
}
}
pub(crate) fn ctx(&mut self) -> PipelineContext<'_> {
PipelineContext {
components: &mut self.components,
blob: &mut self.blob,
profile: &mut self.profile,
resources: &mut self.resources,
frame: FrameContext::new(&self.scratch),
}
}
}
pub(crate) fn bench<R>(name: &str, items: u64, mut body: impl FnMut() -> R) {
let mut iters: u64 = 1;
loop {
let start = Instant::now();
for _ in 0..iters {
std::hint::black_box(body());
}
if start.elapsed().as_nanos() >= TARGET_NS || iters >= MAX_ITERS {
break;
}
iters = iters.saturating_mul(4).min(MAX_ITERS);
}
let start = Instant::now();
for _ in 0..iters {
std::hint::black_box(body());
}
let elapsed = start.elapsed();
let before = concinnity_memory::stats().expect("the test binary tracks its heap");
for _ in 0..iters {
std::hint::black_box(body());
}
let after = concinnity_memory::stats().expect("the allocator stays installed");
let units = (iters * items.max(1)) as f64;
let per_item_ns = elapsed.as_secs_f64() * 1e9 / units;
let allocs = (after.alloc_count - before.alloc_count) as f64 / units;
println!(" {name:<40} {per_item_ns:>10.2} ns/item {allocs:>10.3} allocs/item");
}