othello/benches/generation.rs

199 lines
5.5 KiB
Rust

use std::hint::black_box;
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use othello::{board::BitBoard, game::Team};
const JONS: [&str; 20] = [
"///3bw/3wb",
"///////6bw",
"///////wb",
"wwwwwwww/wwwwwwww/////",
"//1b2w/1bwwww/1bwbww/1bwwww/1b3/",
"///3bw/2bbw/3b//",
"///////bww",
"////bwwwww1b///",
"www/wbw/www////",
"///3b/2bwb/3b//",
"5bw//////",
"///////wb",
"7w/6b/5b",
"w/1b/2b",
"/////5w/6w/7b",
"/////2w/1w/b",
"b/w/w/w//b//",
"////bwwwww1b///",
"///3w///",
"///////",
];
const JON_NAMES: [&str; 20] = [
"starting_position",
"near_endgame",
"corner_setup_a1",
"white_dominance",
"complex_midgame",
"after_first_move",
"edge_capture",
"long_horizontal",
"surrounded_black",
"white_surrounded",
"corner_setup_h8",
"corner_setup_h1",
"diagonal_line",
"short_diagonal",
"anti_diagonal",
"anti_diagonal_short",
"vertical_capture",
"long_horizontal_alt",
"single_piece",
"empty_board",
];
fn bench_available_black(c: &mut Criterion) {
let mut group = c.benchmark_group("available_black");
for (i, jon) in JONS.iter().enumerate() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(
BenchmarkId::new("position", JON_NAMES[i]),
&bb,
|b, board| {
b.iter(|| black_box(board.available(black_box(Team::Black))));
},
);
}
group.finish();
}
fn bench_available_white(c: &mut Criterion) {
let mut group = c.benchmark_group("available_white");
for (i, jon) in JONS.iter().enumerate() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(
BenchmarkId::new("position", JON_NAMES[i]),
&bb,
|b, board| {
b.iter(|| black_box(board.available(black_box(Team::White))));
},
);
}
group.finish();
}
fn bench_available_both_teams(c: &mut Criterion) {
let mut group = c.benchmark_group("available_both_teams");
for (i, jon) in JONS.iter().enumerate() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(
BenchmarkId::new("position", JON_NAMES[i]),
&bb,
|b, board| {
b.iter(|| {
let black_moves = black_box(board.available(Team::Black));
let white_moves = black_box(board.available(Team::White));
black_box((black_moves, white_moves))
});
},
);
}
group.finish();
}
fn bench_available_starting_only(c: &mut Criterion) {
let bb = BitBoard::default();
c.bench_function("starting_position_black", |b| {
b.iter(|| black_box(bb.available(black_box(Team::Black))));
});
c.bench_function("starting_position_white", |b| {
b.iter(|| black_box(bb.available(black_box(Team::White))));
});
}
fn bench_available_worst_case(c: &mut Criterion) {
// Positions that might be slower due to more pieces or complexity
let worst_cases = [
("complex_midgame", "//1b2w/1bwwww/1bwbww/1bwwww/1b3/"),
("white_dominance", "wwwwwwww/wwwwwwww/////"),
("long_capture", "////bwwwww1b///"),
];
let mut group = c.benchmark_group("available_worst_case");
for (name, jon) in worst_cases.iter() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(BenchmarkId::new("black", name), &bb, |b, board| {
b.iter(|| black_box(board.available(Team::Black)));
});
group.bench_with_input(BenchmarkId::new("white", name), &bb, |b, board| {
b.iter(|| black_box(board.available(Team::White)));
});
}
group.finish();
}
fn bench_available_best_case(c: &mut Criterion) {
// Positions that should be fast (empty board, single piece, etc.)
let best_cases = [
("empty_board", "///////"),
("single_piece", "///3w///"),
("corner_only", "///////wb"),
];
let mut group = c.benchmark_group("available_best_case");
for (name, jon) in best_cases.iter() {
let bb = BitBoard::from_jon(jon).expect("Valid JON");
group.bench_with_input(BenchmarkId::new("black", name), &bb, |b, board| {
b.iter(|| black_box(board.available(Team::Black)));
});
group.bench_with_input(BenchmarkId::new("white", name), &bb, |b, board| {
b.iter(|| black_box(board.available(Team::White)));
});
}
group.finish();
}
fn bench_available_all_positions_sequential(c: &mut Criterion) {
let boards: Vec<BitBoard> = JONS
.iter()
.map(|jon| BitBoard::from_jon(jon).expect("Valid JON"))
.collect();
c.bench_function("all_positions_black_sequential", |b| {
b.iter(|| {
for board in &boards {
black_box(board.available(Team::Black));
}
});
});
c.bench_function("all_positions_white_sequential", |b| {
b.iter(|| {
for board in &boards {
black_box(board.available(Team::White));
}
});
});
}
criterion_group!(
benches,
bench_available_black,
bench_available_white,
bench_available_both_teams,
bench_available_starting_only,
bench_available_worst_case,
bench_available_best_case,
bench_available_all_positions_sequential,
);
criterion_main!(benches);