221 lines
7.0 KiB
Rust
221 lines
7.0 KiB
Rust
use std::sync::atomic::{AtomicU32, Ordering};
|
|
|
|
use criterion::{black_box, criterion_group, criterion_main, Bencher, BenchmarkId, Criterion};
|
|
|
|
use battlesnake::types::{
|
|
simulation::Board,
|
|
wire::{Battlesnake, Board as WireBoard, Game, Request, RoyaleSettings, Ruleset, Settings},
|
|
Coord,
|
|
};
|
|
|
|
fn create_start_snake(coord: Coord) -> Battlesnake {
|
|
let id = format!("{coord:?}");
|
|
Battlesnake {
|
|
id: id.clone(),
|
|
name: id.clone(),
|
|
health: 100,
|
|
body: vec![coord; 3],
|
|
latency: "0".into(),
|
|
head: coord,
|
|
length: 3,
|
|
shout: String::new(),
|
|
squad: id,
|
|
}
|
|
}
|
|
|
|
fn create_standard_start_request(starts: [Coord; 4]) -> Request {
|
|
Request {
|
|
game: Game {
|
|
id: "test".into(),
|
|
ruleset: Ruleset {
|
|
name: "standard".into(),
|
|
version: "0".into(),
|
|
settings: Settings {
|
|
food_spawn_chance: 15,
|
|
minimum_food: 1,
|
|
hazard_damage_per_turn: 30,
|
|
royale: RoyaleSettings {
|
|
shrink_every_n_turns: 20,
|
|
},
|
|
},
|
|
},
|
|
map: "standard".into(),
|
|
timeout: 500,
|
|
source: "other".into(),
|
|
},
|
|
turn: 0,
|
|
board: WireBoard {
|
|
height: 11,
|
|
width: 11,
|
|
food: vec![Coord { x: 5, y: 5 }],
|
|
hazards: vec![],
|
|
snakes: vec![
|
|
create_start_snake(starts[0]),
|
|
create_start_snake(starts[1]),
|
|
create_start_snake(starts[2]),
|
|
create_start_snake(starts[3]),
|
|
],
|
|
},
|
|
you: create_start_snake(starts[0]),
|
|
}
|
|
}
|
|
|
|
fn standard(c: &mut Criterion) {
|
|
let turns_min = AtomicU32::new(u32::MAX);
|
|
let turns_max = AtomicU32::new(u32::MIN);
|
|
let turns_sum = AtomicU32::new(0);
|
|
let turns_total = AtomicU32::new(0);
|
|
let mut group = c.benchmark_group("standard");
|
|
group.sample_size(10000);
|
|
|
|
let benchmark = |b: &mut Bencher, board: &Board| {
|
|
b.iter(|| {
|
|
let mut board = board.clone();
|
|
let turn = board.simulate_random(|board| {
|
|
if board.num_snakes() <= 1 {
|
|
Some(board.turn())
|
|
} else {
|
|
None
|
|
}
|
|
});
|
|
|
|
if turn < turns_min.load(Ordering::Relaxed) {
|
|
turns_min.store(turn, Ordering::Relaxed);
|
|
}
|
|
if turn > turns_max.load(Ordering::Relaxed) {
|
|
turns_max.store(turn, Ordering::Relaxed);
|
|
}
|
|
turns_sum.fetch_add(turn, Ordering::Relaxed);
|
|
turns_total.fetch_add(1, Ordering::Relaxed);
|
|
});
|
|
};
|
|
|
|
let request = create_standard_start_request([
|
|
Coord { x: 1, y: 1 },
|
|
Coord { x: 9, y: 1 },
|
|
Coord { x: 1, y: 9 },
|
|
Coord { x: 9, y: 9 },
|
|
]);
|
|
let board = Board::from(&request);
|
|
group.bench_with_input(
|
|
BenchmarkId::from_parameter("start x"),
|
|
black_box(&board),
|
|
benchmark,
|
|
);
|
|
{
|
|
let max = turns_max.load(Ordering::Relaxed);
|
|
let min = turns_min.load(Ordering::Relaxed);
|
|
let sum = turns_sum.load(Ordering::Relaxed);
|
|
let total = turns_total.load(Ordering::Relaxed);
|
|
let avg = sum / total;
|
|
println!("turns: [{min}, {max}] avg {avg} @ {total} samples");
|
|
turns_max.store(u32::MIN, Ordering::Relaxed);
|
|
turns_min.store(u32::MAX, Ordering::Relaxed);
|
|
turns_sum.store(0, Ordering::Relaxed);
|
|
turns_total.store(0, Ordering::Relaxed);
|
|
}
|
|
|
|
let request = create_standard_start_request([
|
|
Coord { x: 5, y: 1 },
|
|
Coord { x: 1, y: 5 },
|
|
Coord { x: 5, y: 9 },
|
|
Coord { x: 9, y: 5 },
|
|
]);
|
|
let board = Board::from(&request);
|
|
group.bench_with_input(
|
|
BenchmarkId::from_parameter("start +"),
|
|
black_box(&board),
|
|
benchmark,
|
|
);
|
|
{
|
|
let max = turns_max.load(Ordering::Relaxed);
|
|
let min = turns_min.load(Ordering::Relaxed);
|
|
let sum = turns_sum.load(Ordering::Relaxed);
|
|
let total = turns_total.load(Ordering::Relaxed);
|
|
let avg = sum / total;
|
|
println!("turns: [{min}, {max}] avg {avg} @ {total} samples");
|
|
}
|
|
}
|
|
|
|
fn constrictor(c: &mut Criterion) {
|
|
let turns_min = AtomicU32::new(u32::MAX);
|
|
let turns_max = AtomicU32::new(u32::MIN);
|
|
let turns_sum = AtomicU32::new(0);
|
|
let turns_total = AtomicU32::new(0);
|
|
let mut group = c.benchmark_group("constrictor");
|
|
group.sample_size(10000);
|
|
|
|
let benchmark = |b: &mut Bencher, board: &Board| {
|
|
b.iter(|| {
|
|
let mut board = board.clone();
|
|
let turn = board.simulate_random(|board| {
|
|
if board.num_snakes() <= 1 {
|
|
Some(board.turn())
|
|
} else {
|
|
None
|
|
}
|
|
});
|
|
|
|
if turn < turns_min.load(Ordering::Relaxed) {
|
|
turns_min.store(turn, Ordering::Relaxed);
|
|
}
|
|
if turn > turns_max.load(Ordering::Relaxed) {
|
|
turns_max.store(turn, Ordering::Relaxed);
|
|
}
|
|
turns_sum.fetch_add(turn, Ordering::Relaxed);
|
|
turns_total.fetch_add(1, Ordering::Relaxed);
|
|
});
|
|
};
|
|
|
|
let mut request = create_standard_start_request([
|
|
Coord { x: 1, y: 1 },
|
|
Coord { x: 9, y: 1 },
|
|
Coord { x: 1, y: 9 },
|
|
Coord { x: 9, y: 9 },
|
|
]);
|
|
request.game.ruleset.name = "constrictor".into();
|
|
let board = Board::from(&request);
|
|
group.bench_with_input(
|
|
BenchmarkId::from_parameter("start x"),
|
|
black_box(&board),
|
|
benchmark,
|
|
);
|
|
{
|
|
let max = turns_max.load(Ordering::Relaxed);
|
|
let min = turns_min.load(Ordering::Relaxed);
|
|
let sum = turns_sum.load(Ordering::Relaxed);
|
|
let total = turns_total.load(Ordering::Relaxed);
|
|
let avg = sum / total;
|
|
println!("turns: [{min}, {max}] avg {avg} @ {total} samples");
|
|
turns_max.store(u32::MIN, Ordering::Relaxed);
|
|
turns_min.store(u32::MAX, Ordering::Relaxed);
|
|
turns_sum.store(0, Ordering::Relaxed);
|
|
turns_total.store(0, Ordering::Relaxed);
|
|
}
|
|
|
|
let mut request = create_standard_start_request([
|
|
Coord { x: 5, y: 1 },
|
|
Coord { x: 1, y: 5 },
|
|
Coord { x: 5, y: 9 },
|
|
Coord { x: 9, y: 5 },
|
|
]);
|
|
request.game.ruleset.name = "constrictor".into();
|
|
let board = Board::from(&request);
|
|
group.bench_with_input(
|
|
BenchmarkId::from_parameter("start +"),
|
|
black_box(&board),
|
|
benchmark,
|
|
);
|
|
{
|
|
let max = turns_max.load(Ordering::Relaxed);
|
|
let min = turns_min.load(Ordering::Relaxed);
|
|
let sum = turns_sum.load(Ordering::Relaxed);
|
|
let total = turns_total.load(Ordering::Relaxed);
|
|
let avg = sum / total;
|
|
println!("turns: [{min}, {max}] avg {avg} @ {total} samples");
|
|
}
|
|
}
|
|
|
|
criterion_group!(benches, standard, constrictor);
|
|
criterion_main!(benches);
|