diff --git a/benches/benchmark.rs b/benches/benchmark.rs index cc2ed77..ce51364 100644 --- a/benches/benchmark.rs +++ b/benches/benchmark.rs @@ -1,23 +1,35 @@ -use criterion::{BenchmarkId, measurement::Measurement}; -use criterion::{criterion_group, criterion_main, Criterion, Throughput, BenchmarkGroup}; +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use gntag::agent::{Agent, SimpleAgent}; use gntag::world::ActualWorld; -fn world(mut group: BenchmarkGroup, validate: bool) { +fn get_world(width: isize, spacing: usize, validate: bool) -> ActualWorld { + let mut agents = vec![]; + for x in (0..width).step_by(spacing) { + for y in (0..width).step_by(spacing) { + agents.push(((x, y).into(), Box::new(SimpleAgent) as Box)); + } + } + ActualWorld::new((width, width).into(), agents, validate) +} + +fn world(c: &mut Criterion) { + let mut group = c.benchmark_group("world"); let width: isize = 1000; - for spacing in (50..100).step_by(10) { + for spacing in (50..=100).step_by(25) { group.throughput(Throughput::Elements((width / spacing).pow(2) as u64)); group.bench_with_input( - BenchmarkId::from_parameter(spacing), + BenchmarkId::new("validating", spacing), &spacing, |b, &spacing| { - let mut agents: Vec<(_, Box)> = vec![]; - for x in (0..width).step_by(spacing as usize) { - for y in (0..width).step_by(spacing as usize) { - agents.push(((x, y).into(), Box::new(SimpleAgent))); - } - } - let mut world = ActualWorld::new((width, width).into(), agents, validate); + let mut world = get_world(width, spacing as usize, true); + b.iter(|| world.do_step()); + }, + ); + group.bench_with_input( + BenchmarkId::new("non-validating", spacing), + &spacing, + |b, &spacing| { + let mut world = get_world(width, spacing as usize, false); b.iter(|| world.do_step()); }, ); @@ -25,17 +37,7 @@ fn world(mut group: BenchmarkGroup, validate: bool) { group.finish(); } -fn world_validating(c: &mut Criterion) { - let group = c.benchmark_group("world_validating"); - world(group, true) -} - -fn world_nonvalidating(c: &mut Criterion) { - let group = c.benchmark_group("world_nonvalidating"); - world(group, false) -} - -criterion_group!(benches, world_validating, world_nonvalidating); +criterion_group!(benches, world); criterion_main!(benches); // 5000/1000 -> 9,993 diff --git a/src/agent.rs b/src/agent.rs index 2fdc50b..260a922 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -1,5 +1,6 @@ pub type Distance = isize; +#[derive(Clone)] pub struct Position { pub x: Distance, pub y: Distance, @@ -25,12 +26,12 @@ impl From<(Distance, Distance)> for Direction { pub type AgentId = usize; -pub struct WorldView { +pub struct WorldView<'o> { pub self_id: AgentId, pub tagged: AgentId, pub tagged_by: Option, pub bounds_distance: (Distance, Distance, Distance, Distance), - pub other_agents: Vec<(Direction, AgentId)>, + pub other_agents: &'o mut dyn Iterator, } #[derive(Debug)] diff --git a/src/world.rs b/src/world.rs index 9eb2c49..581d006 100644 --- a/src/world.rs +++ b/src/world.rs @@ -58,7 +58,7 @@ impl ActualWorld { tagged_by: self.state.tagged_by, tagged: self.state.tagged, bounds_distance: (pos.y, self.size.x - pos.x, self.size.y - pos.y, pos.x), - other_agents: self + other_agents: &mut self .state .agent_positions .iter() @@ -71,8 +71,7 @@ impl ActualWorld { }, *id, ) - }) - .collect(), + }), }), ) }) @@ -87,6 +86,7 @@ impl ActualWorld { self.check_move(id, &mv); } let mut new_pos = None; + let pos = self.state.agent_positions.get(&id).unwrap(); match mv { Move::Noop => {} Move::TryTag(other_id) => { @@ -94,14 +94,12 @@ impl ActualWorld { new_state.tagged_by = Some(id); } Move::TryMove(dir) => { - let pos = self.state.agent_positions.get(&id).unwrap(); new_pos = Some((pos.x + dir.x, pos.y + dir.y).into()); } } - new_state.agent_positions.insert( - id, - new_pos.unwrap_or_else(|| self.state.agent_positions.remove(&id).unwrap()), - ); + new_state + .agent_positions + .insert(id, new_pos.unwrap_or_else(|| pos.clone())); } self.state = new_state; }