Skip to content

Commit 95b7735

Browse files
committed
1 parent 5078375 commit 95b7735

4 files changed

Lines changed: 268 additions & 1 deletion

File tree

.github/workflows/benchmark.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Benchmark PR
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [master]
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
benchmark:
18+
name: Run benchmarks (instruction counts)
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- uses: dtolnay/rust-toolchain@stable
24+
25+
# Install valgrind and iai-callgrind-runner
26+
- name: Install dependencies
27+
run: |
28+
sudo apt-get update && sudo apt-get install -y valgrind
29+
cargo install iai-callgrind-runner
30+
31+
- name: Run benchmarks on PR branch
32+
if: github.event_name == 'pull_request'
33+
run: |
34+
cargo bench --bench generate_moves_iai
35+
# Save the results
36+
mkdir -p benchmark-results-pr
37+
cp -r target/iai benchmark-results-pr/ || true
38+
39+
- name: Run benchmarks on master
40+
if: github.event_name == 'push'
41+
run: cargo bench --bench generate_moves_iai
42+
43+
- name: Checkout base branch
44+
if: github.event_name == 'pull_request'
45+
uses: actions/checkout@v4
46+
with:
47+
ref: ${{ github.base_ref }}
48+
clean: false
49+
50+
- name: Run benchmarks on base branch
51+
if: github.event_name == 'pull_request'
52+
run: |
53+
cargo bench --bench generate_moves_iai
54+
mkdir -p benchmark-results-base
55+
cp -r target/iai benchmark-results-base/ || true
56+
57+
- name: Compare benchmarks
58+
if: github.event_name == 'pull_request'
59+
run: |
60+
echo "## 📊 Benchmark Results (Instruction Counts)" > benchmark_results.md
61+
echo "" >> benchmark_results.md
62+
echo "Comparing \`${{ github.head_ref }}\` (PR) vs \`${{ github.base_ref }}\` (base)" >> benchmark_results.md
63+
echo "" >> benchmark_results.md
64+
echo "**Using iai-callgrind:** Counts instructions via Cachegrind - deterministic and not affected by CI noise." >> benchmark_results.md
65+
echo "" >> benchmark_results.md
66+
echo '```' >> benchmark_results.md
67+
# Show recent benchmark output
68+
find target/iai -name "*.txt" -type f -exec tail -50 {} \; 2>/dev/null | head -100 >> benchmark_results.md || echo "See job logs for detailed results" >> benchmark_results.md
69+
echo '```' >> benchmark_results.md
70+
echo "" >> benchmark_results.md
71+
echo "<sub>📏 Instruction counts via Cachegrind. Lower is better. Results are deterministic.</sub>" >> benchmark_results.md
72+
73+
- name: Comment PR with results
74+
if: github.event_name == 'pull_request'
75+
uses: thollander/actions-comment-pull-request@v2
76+
with:
77+
filePath: benchmark_results.md
78+
comment_tag: benchmark_results

Cargo.lock

Lines changed: 104 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

check-buddy/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ thiserror = "2"
1818
calamine = "0.32.0"
1919
criterion = "0.8.1"
2020
csv = "1.4.0"
21-
21+
iai-callgrind = "0.16"
22+
2223
[[bench]]
2324
name = "generate_moves"
2425
harness = false
26+
27+
[[bench]]
28+
name = "generate_moves_iai"
29+
harness = false
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use check_buddy::piece_type::PieceType;
2+
use check_buddy::BoardMap;
3+
use iai_callgrind::{library_benchmark, library_benchmark_group, main};
4+
use std::hint::black_box;
5+
6+
#[library_benchmark]
7+
fn single_move() {
8+
let board = BoardMap::starting();
9+
black_box(board.gen_to_positions(black_box([0, 0])));
10+
}
11+
12+
#[library_benchmark]
13+
fn opponent_moves() {
14+
let board = BoardMap::starting();
15+
black_box(board.gen_all_opponent_positions());
16+
}
17+
18+
#[library_benchmark]
19+
fn all_moves() {
20+
let board = BoardMap::starting();
21+
black_box(
22+
(0..8)
23+
.flat_map(|rank| {
24+
(0..8)
25+
.map(|file| board.gen_to_positions(black_box([rank, file])))
26+
.collect::<Vec<_>>()
27+
})
28+
.collect::<Vec<_>>(),
29+
);
30+
}
31+
32+
#[library_benchmark]
33+
fn all_legal_moves() {
34+
let board = BoardMap::starting();
35+
black_box(
36+
(0..8)
37+
.flat_map(|rank| {
38+
(0..8)
39+
.map(|file| board.gen_legal_positions(black_box([rank, file])))
40+
.collect::<Vec<_>>()
41+
})
42+
.collect::<Vec<_>>(),
43+
);
44+
}
45+
46+
#[library_benchmark]
47+
fn pawn() {
48+
let board = BoardMap::starting();
49+
black_box(board.gen_pawn(black_box([1, 0])));
50+
}
51+
52+
#[library_benchmark]
53+
fn king() {
54+
let board = BoardMap::starting();
55+
black_box(board.gen_king(black_box([0, 4])));
56+
}
57+
58+
#[library_benchmark]
59+
fn knight() {
60+
let board = BoardMap::starting();
61+
black_box(board.gen_knight(black_box([0, 1])));
62+
}
63+
64+
#[library_benchmark]
65+
fn queen() {
66+
let board = BoardMap::starting();
67+
black_box(board.gen_sliding(black_box([0, 1]), PieceType::Queen));
68+
}
69+
70+
library_benchmark_group!(
71+
name = generate_moves;
72+
benchmarks = single_move, opponent_moves, all_moves, all_legal_moves
73+
);
74+
75+
library_benchmark_group!(
76+
name = generate_piece_moves;
77+
benchmarks = pawn, king, knight, queen
78+
);
79+
80+
main!(library_benchmark_groups = generate_moves, generate_piece_moves);

0 commit comments

Comments
 (0)