Skip to main content

scene_admission/
scene_admission.rs

1// =============================================================================
2//        #######
3//     ###       ###     F: scene_admission.rs
4//    ##   ## ##   ##    P: AppCore-Runtime
5//         ## ##
6//                       C: 2026/10/15 08:11:39 by dnettoRaw
7//    ##   ## ##   ##    U: 2026/10/15 10:24:40 by dnettoRaw
8//      ###########      S: 0.1.0-alpha.1
9// =============================================================================
10
11//! Bounded CPU slot-admission profile, excluding world/asset allocation and GPU work.
12use appcore_render::*;
13use std::{hint::black_box, time::Instant};
14
15type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
16fn sample(count: u32, binding: RenderBinding) -> Result<(u128, u128, u64)> {
17    let limits = SceneLimits {
18        max_entities: count,
19        max_snapshot_instances: count,
20        max_snapshots: 1,
21        managed_cpu_bytes: 512 * 1024 * 1024,
22    };
23    let bytes = limits.reservation_bytes()?;
24    let mut world = SceneWorld::new(limits)?;
25    let mut entities = Vec::with_capacity(count as usize);
26    let started = Instant::now();
27    for _ in 0..count {
28        entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
29    }
30    let initial = started.elapsed().as_nanos();
31    let started = Instant::now();
32    for id in entities.drain(..) {
33        world.despawn(black_box(id))?;
34    }
35    for _ in 0..count {
36        entities.push(world.spawn(black_box(Transform::default()), black_box(binding), None)?);
37    }
38    let reuse = started.elapsed().as_nanos();
39    black_box((&world, &entities));
40    assert_eq!(world.len(), count as usize);
41    Ok((initial, reuse, bytes))
42}
43fn main() -> Result<()> {
44    let mut assets = ResourceArena::new(RenderLimits::default())?;
45    let binding = RenderBinding {
46        mesh: assets.insert((), 1)?,
47        material: assets.insert((), 1)?,
48        tint: [1.; 4],
49        animation: 0,
50        morph: 0,
51    };
52    eprintln!("CPU admission only; target={}/{}; 1 warmup + 5 samples per size; release build required; allocation/drop excluded; reuse=despawn all + spawn all", std::env::consts::OS, std::env::consts::ARCH);
53    println!("entities,initial_median_ns,initial_min_ns,initial_max_ns,reuse_median_ns,reuse_min_ns,reuse_max_ns,reservation_bytes");
54    for count in [1024, 8192, 32768] {
55        black_box(sample(count, binding)?);
56        let mut initial = [0; 5];
57        let mut reuse = [0; 5];
58        let mut bytes = 0;
59        for i in 0..5 {
60            let result = sample(count, binding)?;
61            (initial[i], reuse[i], bytes) = result;
62        }
63        initial.sort_unstable();
64        reuse.sort_unstable();
65        println!(
66            "{count},{},{},{},{},{},{},{bytes}",
67            initial[2], initial[0], initial[4], reuse[2], reuse[0], reuse[4]
68        );
69    }
70    Ok(())
71}