From 97d914238ca478171f9e92fd2f6efe7d99a1be0d Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Fri, 28 Feb 2025 20:53:36 -0500 Subject: [PATCH] bench: add board place benchmark --- Cargo.toml | 4 ++++ benches/board.rs | 29 +++++++++++++++++++++++++++++ benches/future_children.rs | 2 +- src/repr/board.rs | 3 ++- src/repr/chains.rs | 2 +- 5 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 benches/board.rs diff --git a/Cargo.toml b/Cargo.toml index f21c2cf..923c6c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,10 @@ criterion = { version = "0.5", features = [ "html_reports" ] } name = "future_children" harness = false +[[bench]] +name = "board" +harness = false + [lints.rust] # fix weird warnings about `test` not being expected unexpected_cfgs = { level = "allow", check-cfg = ['cfg(test)'] } diff --git a/benches/board.rs b/benches/board.rs new file mode 100644 index 0000000..5ee12d7 --- /dev/null +++ b/benches/board.rs @@ -0,0 +1,29 @@ +use criterion::{criterion_group, criterion_main, Criterion, Throughput}; +use othello::repr::{Board, Piece}; + +fn fill_board(loops: usize) { + let mut board = Board::new(); + board.place_unchecked((0, 1).into(), Piece::White); + board.place_unchecked((0, 2).into(), Piece::Black); + board.place_unchecked((0, 3).into(), Piece::Black); + board.place_unchecked((0, 4).into(), Piece::Black); + for _ in 0..loops { + let mut board = board; + let _ = board.place((0, 5).into(), Piece::White); + } +} + +fn criterion_benchmark(c: &mut Criterion) { + let mut group = c.benchmark_group("board"); + + const LOOPS: usize = 1000; + + group.throughput(Throughput::Elements(LOOPS as u64)); + group.bench_function("board_place", |b| { + b.iter(|| fill_board(LOOPS)); + }); + group.finish(); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/benches/future_children.rs b/benches/future_children.rs index 5b9588a..02c9024 100644 --- a/benches/future_children.rs +++ b/benches/future_children.rs @@ -22,7 +22,7 @@ fn criterion_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("extend_layer (no pruning)"); const ARENA_SIZE: usize = 10_000_000; - for depth in 1..8 { + for depth in 6..8 { group.throughput(Throughput::Elements( extend_layers_no_pruning(depth, ARENA_SIZE) as u64, )); diff --git a/src/repr/board.rs b/src/repr/board.rs index 4030f83..27af858 100644 --- a/src/repr/board.rs +++ b/src/repr/board.rs @@ -162,8 +162,9 @@ impl Board { } /// Place a piece without checking for propegation of validity + /// only pub for setting up benchmark #[const_fn(cfg(not(feature = "bitvec")))] - const fn place_unchecked(&mut self, coord: CoordPair, piece: Piece) { + pub const fn place_unchecked(&mut self, coord: CoordPair, piece: Piece) { self.board_mut(piece).set(coord, true); self.board_mut(piece.flip()).set(coord, false); } diff --git a/src/repr/chains.rs b/src/repr/chains.rs index 6566853..e87f749 100644 --- a/src/repr/chains.rs +++ b/src/repr/chains.rs @@ -84,7 +84,7 @@ pub fn gen_adj_lookup() -> PosMap { .map(Iterator::collect), ) .chain(diag_raw(i_chain, j_chain).map(Iterator::collect)) - .filter(|x: &Vec<(u8, u8)>| !x.is_empty()) // PERF! filter out empty chains +~10-12% perf boost + .filter(|x: &Vec<(u8, u8)>| !x.is_empty()) // PERF! filter out empty chains +~5% perf boost (in [`Board::place`]) .map(|x: Vec<(u8, u8)>| x.into_iter().map(|x| x.into()).collect()), );