ab4a7899af
build / mod (push) Successful in 3m25s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
60 lines
2.4 KiB
Rust
60 lines
2.4 KiB
Rust
//! Rough cost of handing 2000 model instances to the game each tick: allocations and bytes the mod
|
|
//! builds (counting allocator) and the bytes the canonical ABI then copies across (wasm32 layout:
|
|
//! `model-instance` 64 bytes + its name, `model-instance-id` 56 bytes).
|
|
//! Run: `cargo run --release --example emit_cost`.
|
|
use horizon_mod_sdk::render::{ModelInstance, ModelInstanceId};
|
|
use std::alloc::{GlobalAlloc, Layout, System};
|
|
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
|
|
|
|
static COUNT: AtomicUsize = AtomicUsize::new(0);
|
|
static BYTES: AtomicUsize = AtomicUsize::new(0);
|
|
struct Counting;
|
|
unsafe impl GlobalAlloc for Counting {
|
|
unsafe fn alloc(&self, l: Layout) -> *mut u8 {
|
|
COUNT.fetch_add(1, Relaxed);
|
|
BYTES.fetch_add(l.size(), Relaxed);
|
|
unsafe { System.alloc(l) }
|
|
}
|
|
unsafe fn dealloc(&self, p: *mut u8, l: Layout) {
|
|
unsafe { System.dealloc(p, l) }
|
|
}
|
|
}
|
|
#[global_allocator]
|
|
static A: Counting = Counting;
|
|
|
|
const NAMES: [&str; 4] = ["airdef:shahed", "airdef:geran_2", "airdef:iris_t", "airdef:explosion_core"];
|
|
|
|
fn measure(f: impl FnOnce()) -> (usize, usize) {
|
|
let (c, b) = (COUNT.load(Relaxed), BYTES.load(Relaxed));
|
|
f();
|
|
(COUNT.load(Relaxed) - c, BYTES.load(Relaxed) - b)
|
|
}
|
|
|
|
fn main() {
|
|
const N: usize = 2000;
|
|
let (mut old, mut by_id): (Vec<ModelInstance>, Vec<ModelInstanceId>) = (Vec::new(), Vec::new());
|
|
by_id.reserve(N);
|
|
let inst = |i: usize| (i as u32, NAMES[i % 4], i as f64);
|
|
let wire_old: usize = (0..N).map(|i| 64 + NAMES[i % 4].len()).sum();
|
|
let (c, b) = measure(|| {
|
|
old = (0..N)
|
|
.map(|i| {
|
|
let (id, n, x) = inst(i);
|
|
ModelInstance { id, model: n.to_string(), x, y: x, z: x, rotation: (0., 0., 0., 1.), scale: 1., glow: false }
|
|
})
|
|
.collect();
|
|
});
|
|
println!("old : {c} allocations, {b} bytes built per tick; {wire_old} bytes across, {N} strings lowered");
|
|
drop(old);
|
|
for tick in 0..2 {
|
|
let (c, b) = measure(|| {
|
|
by_id.clear();
|
|
for i in 0..N {
|
|
let (id, _, x) = inst(i);
|
|
by_id.push(ModelInstanceId { id, model: (i % 4) as u32, x, y: x, z: x, rotation: (0., 0., 0., 1.), scale: 1., glow: false });
|
|
}
|
|
});
|
|
println!("new : tick {tick}: {c} allocations, {b} bytes built; {} bytes across, no strings", N * 56);
|
|
}
|
|
}
|