// ⏱️ 실제 물리 TPS(Ticks Per Second) 실측 벤치마크 (src/bin/bench_tps.rs) use std::time::Instant; use rand::Rng; #[derive(Copy, Clone, Debug, PartialEq)] pub enum PhaseState { HyperInhibition, StandardInhibition, SubInhibition, NegQuiescent, PosQuiescent, SubExcitation, StandardExcitation, HyperExcitation, } impl PhaseState { pub fn value(&self) -> f32 { match self { PhaseState::HyperInhibition => -2.0, PhaseState::StandardInhibition => -1.0, PhaseState::SubInhibition => -0.5, PhaseState::NegQuiescent => -0.01, PhaseState::PosQuiescent => 0.01, PhaseState::SubExcitation => 0.5, PhaseState::StandardExcitation => 1.0, PhaseState::HyperExcitation => 2.0, } } pub fn from_energy(e: f32) -> Self { if e <= -1.5 { PhaseState::HyperInhibition } else if e <= -0.75 { PhaseState::StandardInhibition } else if e <= -0.25 { PhaseState::SubInhibition } else if e <= 0.0 { PhaseState::NegQuiescent } else if e <= 0.25 { PhaseState::PosQuiescent } else if e <= 0.75 { PhaseState::SubExcitation } else if e <= 1.5 { PhaseState::StandardExcitation } else { PhaseState::HyperExcitation } } } pub struct BioPhysEngine { pub size: usize, pub bedrock: Vec, pub topsoil: Vec, pub mutation_rate: f32, } impl BioPhysEngine { pub fn new(size: usize, mutation_rate: f32) -> Self { let mut rng = rand::thread_rng(); let bedrock: Vec = (0..size * size).map(|_| rng.gen_range(-1.0..1.0)).collect(); let topsoil: Vec = (0..size * size).map(|_| PhaseState::from_energy(rng.gen_range(-2.0..2.0))).collect(); BioPhysEngine { size, bedrock, topsoil, mutation_rate } } #[inline(always)] pub fn step(&mut self) { let s = self.size as i32; let mut next_topsoil = self.topsoil.clone(); for y in 0..s { for x in 0..s { let idx = (y * s + x) as usize; let neighbors = [ ((y - 1 + s) % s * s + x) as usize, ((y + 1) % s * s + x) as usize, (y * s + (x - 1 + s) % s) as usize, (y * s + (x + 1) % s) as usize, ]; let neighbor_energy = ( self.topsoil[neighbors[0]].value() + self.topsoil[neighbors[1]].value() + self.topsoil[neighbors[2]].value() + self.topsoil[neighbors[3]].value() ) * 0.25; let local_field = neighbor_energy + self.bedrock[idx]; next_topsoil[idx] = PhaseState::from_energy(local_field); } } self.topsoil = next_topsoil; } } fn main() { println!("============================================================"); println!(" ⚡ BioPhys 8-State 엔진 실제 하드웨어 TPS 실측 벤치마크"); println!("============================================================\n"); let grid_size = 16; let total_ticks = 50_000; let mut engine = BioPhysEngine::new(grid_size, 0.0); // 워밍업 (1,000 Ticks) for _ in 0..1000 { engine.step(); } println!("🚀 [벤치마크 시작] 16x16 격자 (256 노드), 총 {} Ticks 연산 중...", total_ticks); let start_time = Instant::now(); for _ in 0..total_ticks { engine.step(); } let elapsed = start_time.elapsed(); let elapsed_sec = elapsed.as_secs_f64(); let tps = (total_ticks as f64) / elapsed_sec; let cell_updates_per_sec = (total_ticks as f64 * (grid_size * grid_size) as f64) / elapsed_sec; println!("\n============================================================"); println!(" 📊 실측 벤치마크 결과 (Hardware Measured)"); println!("============================================================"); println!(" ⏱️ 총 소요 시간 : {:.4} 초 ({:?})", elapsed_sec, elapsed); println!(" 🔄 총 실행 틱(Ticks) : {} Ticks", total_ticks); println!(" ⚡ 실제 물리 TPS : {:.2} Ticks/sec", tps); println!(" 🧬 초당 격자 셀 갱신 : {:.2} MCell/sec (Mega-Updates)", cell_updates_per_sec / 1_000_000.0); println!("============================================================"); }