Drop7 Research
← Experiments

Rust bitboard engine: parity gates and throughput benchmark vs TypeScript and C++ engines

completedtier CHECKengineeringno-gameplaynot-applicableEX-20260824-rust-engine-parity-throughput-4036a91f
No explanation has been written for this experiment yet. Add web/content/research/EX-20260824-rust-engine-parity-throughput-4036a91f.mdx and it will appear here. The registered protocol is shown below.

The registered protocol

Engineering port, no new science: a column-major nibble-packed Rust reimplementation of the Drop7 engine (7 x u32, 4 bits per cell; gravity as PEXT compaction; whole-board cover-hit counting with a bitboard adder) plus a packed-key transposition-table expectimax search is trace-equivalent to the frozen C++ reference (src/core/native/engine.hpp), the proven C++ fast engine (approaches/lifetime-objective/fast-engine, finding-13/audit-06), and the TypeScript engine (src/core/typescript/engine.ts): identical boards, scores, wave lists, reveal streams, leaf value bit patterns, per-column search values and chosen actions at fixed depth/strata. Expected speedup: at least the C++ fast engine's decisions/second at identical fixed work, with bounded per-searcher memory and near-linear game-level thread scaling; the realised figures are measured and reported with the machine profile. Per docs/benchmarks.md, any deviation in actions, random events, or work semantics reclassifies the port as a new algorithmic candidate and it is then not accepted under this record.

Candidate
rust-engine (drop7-rs cargo crate, std-only)
approaches/fair-expectimax/rust-engine/src/lib.rs
Comparator
C++ fast engine + frozen native reference + TypeScript engine
approaches/lifetime-objective/fast-engine/fast-search.hpp

Primary metric

trace equivalence vs the C++ reference and fast engine: board, score, next disc, wave list, reveal stream on every move; leaf value uint64 bit patterns; per-column search values and chosen actions at fixed depth/strata

Statistical unit: not-applicable

Pass criteria, fixed in advance

  • Trajectory gate: >= 4096 complete games per policy arm (center policy and a searching policy) replayed move-by-move through the Rust engine and the C++ reference/fast engine with 0 mismatches on board, next disc, score, score delta, wave list, level, moves remaining, terminal flag.
  • Leaf gate: >= 100,000 real leaf states with uint64-bit-identical leaf values vs the C++ fast leaf.
  • Search gate: >= 500 real root decisions at d4s7 and a d5s7 probe set with per-column double values bit-identical to the C++ fast search and identical chosen actions; identical completed depths at fixed work bounds.
  • Determinism: byte-identical chosen actions across worker counts (1 vs 32) in complete-depth mode and across repeated runs; reflection gate mirrors the C++ behavior.
  • TypeScript cross-check: >= 1000 games replayed through the TS engine and the Rust engine from the same Mulberry32 draw stream with identical boards and scores.
  • npm test and make test pass; no existing file is modified.

On pass: Record valid + pass (engineering, CHECK tier) with measured throughput, memory and scaling figures and the machine profile; publish the comparative writeup as the approach page; no strength claim and no later cohort is opened by this record.

On fail: Record valid + fail as an engineering result; the C++ fast engine remains the fastest proven-equivalent implementation.

Data and reuse

Zero new leased seeds. Trajectory and search gates read sub-blocks of the already-opened SEEDLEASE-A52-FAST development block 0xa5270000-0xa5277fff (docs/exploratory/lease-map.md, opened for semantics-preserving engine optimisation): Rust uses 0xa5276000-0xa5276fff (gates) and 0xa5277000-0xa5277fff (timing), disjoint from the C++ sub-blocks at 0xa5270000-0xa5275fff. CHECK probes may also read the already-open 0xa5278000-0xa52784ff probe block. No cohort's data status changes; no strength claim is made.

seed leases: none

What happened

valid run · outcome: passsupported-as-testedmechanics-onlyRS-20260824T075451Z-e89ea128

The Rust bitboard engine is trace-equivalent to the frozen C++ reference, the proven C++ fast engine, and the TypeScript engine on every observable, and is the fastest of the three. Board representation is seven u32 column words at 4 bits per cell (28 bytes): gravity is a single PEXT bit-gather per column, a row rise is (word << 4) | SOLID, and cover hits are counted board-wide with a 4-way bitboard parallel counter. All parity gates pass with zero mismatches: 3 trajectory arms (512 center + 256 search-policy games vs C++ playHeadlessMove; 256 games vs the TypeScript seededRandom driver) totalling 36,427 moves and 40,286 waves; 150,854 leaf states bit-identical as uint64 patterns; 105 d4s7 and 10 d5s7 roots with bit-identical per-column values and identical actions; the values gate re-run with the transposition table enabled proves cache-independence. Measured on the shared AMD Ryzen AI MAX+ 395 workstation (best-of-N, load 1.1-1.7): single-core engine throughput 12.8M moves/s vs C++ fast 6.5M (1.97x) and TypeScript 0.65M (19.8x); leaf 155.6 ns vs C++ fast 187.5 ns (1.20x); fair search at d4s7 908 ms/decision vs C++ fast 1,071 ms (1.18x) with a 3.1 MB direct-mapped table vs the C++ 16.2 MB LRU; d5s7 7,047 ms at 1M entries vs 7,817 ms (1.11x). Game-level scaling is shared-nothing and near-linear (10.3x on 16 physical cores on the shared machine; 14.1x in a clean run), with identical results at every worker count. A key recorded finding: the transposition table's 1.3% node hit rate is misleading — each hit prunes a whole subtree, so the table eliminates ~47% of work at d4s7 and ~90% at d5s7, and a cheap direct-mapped depth-preferred table captures nearly all of the strict-LRU table's payoff at a fifth of the memory. No strength claim; no new seeds opened.

What it had to pass
  • Trajectory parity vs C++ reference and TypeScript engine across center, search-policy, and TS-driver arms — observed: 3 arms, 36,427 moves, 40,286 waves, 0 mismatches on board, next disc, score, score delta, wave list, level, moves remaining, terminal/clear/advance flags
  • Leaf bit-exactness vs C++ fastFairLeaf as uint64 bit patterns — observed: 150,854 states, 0 mismatches
  • Search value/action parity at fixed depth/strata — observed: 105 d4s7 roots (no-table and depth-gated arms) + 10 d5s7 roots, per-column f64 bit patterns and chosen actions identical, 0 mismatches
  • Cache independence of the transposition table — observed: values gate re-run with the direct-mapped table enabled: 105 roots, 0 mismatches
  • Worker-count independence and determinism — observed: identical move counts, wave counts and mean scores at 1/2/4/8/16/32 game-level workers; each game computed by exactly one worker
  • npm test and make test pass; no existing file modified — observed: npm test 137/137 pass; make research-validate OK; all Rust/C++/TS additions live under approaches/fair-expectimax/rust-engine/ and build/rust-engine/
Recorded metrics
engineMovesPerSecond
typescript
649,471
cppReference
6,799,180
cppFast
6,511,760
rust
12,838,933
leafNsPerEval
cppFast
187.5000
rust
155.6000
searchD4S7MsPerDecision
cppBaseline
3247.8000
cppFast
1071.5000
rustNoTable
1633.4000
rustDepthGated64k
907.6000
searchD5S7MsPerDecision
cppBaseline
23992.6000
cppFast
7817.3000
rustNoTable
63325.4000
rustDepthGated256k
7787.9000
rustDepthGated1M
7047.1000
rustDepthGated4M
6748.4000
transpositionWorkReduction
nodeHitRateD4S7
0.0130
nodeHitRateD5S7
0.0136
workEliminatedD4S7
11.9M -> 6.3M (47%)
workEliminatedD5S7
582.7M -> 59.5M (90%)
scalingMovesPerSecond16Threads
rust
129,483,860
cppFast
82,364,000
memoryBytes
rustSearcher
2,496
rustBoard
28
rustTable64k
3,145,728
cppFastTable
16,194,304
Limitations
  • CHECK-tier engineering result: proves equivalence and measures speed/memory, but makes no policy-strength claim and advances no benchmark tier.
  • Timing measured on a shared workstation (load average 1.1-1.7); ratios between back-to-back arms are the trustworthy quantity, absolute nanoseconds are not.
  • The d5s7 arms ran 3 decisions each (1 repeat) because a single d5s7 decision costs 7-63 s; the d4s7 arms ran 21 decisions, best of 3.
  • The direct-mapped table's hit rate at d5s7 (748k-825k hits/decision) trails the C++ strict-LRU table (911k); a set-associative table is the recorded reopening direction.
  • No GPU, latent-mode, or native-scenario variant: scripted-round and scenario duties stay with the existing engines.