Repository navigation
refactor(hexmap): shared primitives, cross-lot gas and CI time (P1) - #135
Merged
Merged
Conversation
… Bits Bits::bitwise wraps the private corelib libfunc (AND, XOR and OR in one application), Bits::and/or/xor apply it per limb. The local declarations of caver, bfs, dial and their benches are removed. Bits::popcount now sums the byte counts of both limbs (L7 winner, 15.6k vs 19.0k per op), Bits::popcount_small and Bits::byte_counts serve the spreader. The first SWAR popcount stays in bench_spreader as the measured loser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rs to Layout Layout::expand and expand_small now run the L1 formulation (limbs, bitwise triple, up/down from X = 2P - Pe with one product each) through the 4-value Dilation constants carried by the layer loops; Layout::with_interior builds the layout and the interior mask from 3 shared lookups. Bfs drops its Step and its private dilation, Dial its dilations; both take their edge endpoints from Layout::edge_neighbours and Layout::neighbour_in. The generic Set<T> of Dial moves to Bits. Caver::keep_component floods the frontier through BfsInternal::component (cave -5.6 %, maze -10.6 %, serpentine -11.5 %), and Caver::generate shares the layout lookups. The L0 forms stay in Variants for the loser benchmarks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spreader fuzz benchmarks took 6 of the 8 minutes of the hexmap job. The 100 loser benchmarks are #[ignore]d and run, with the library fuzz tests on 256 seeds, in the non-blocking hexmap-full job on pushes to main (snforge test --include-ignored). The library fuzz benchmarks take their runs from the command line: 64 seeds in the pull-request job, their budgets (max over 256 seeds) unchanged. Local run with a fresh build: 7m55s -> 2m46s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… 216, 720 The pool is refilled below 2^64 instead of 2^32: the modulo bias falls from 2^-24 to 2^-56 per pool (2^-54.5 for shuffle6) at no measurable cost on the generators (mazer per tile 31.87k vs 31.88k). Rng::draw6, Rng::shuffle6 and Rng::split216 divide by their constant with core::internal::bounded_int (1.10k vs 1.56k per division): mazer -1.4 % (order 0) and -2.2 % (order 1) per carved tile over 8 seeds, digger maze -4.2 %, walker -2.0 % to -2.4 %. The walker draws 6 triples per pool and takes both limbs of each permutation. A spare pool kept in Rng (all the outputs of a permutation) and a counter refill were measured and lose (+2 % per tile: one more field through the recursion). Exact-grid expectations of the mazer, digger and walker tests are regenerated; the reference walker follows the new stream. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The public traits of Mazer, Digger and Spreader keep their documented functions only (generate, maze, corridor); the recursion, the dig and the selection helpers move to pub(crate) MazerInternal, DiggerInternal and SpreaderInternal. BfsInternal, Back, Endpoint, the stores and goals of Bfs, Carver, Heading, TurnTrait, BitSetTrait and Counts become pub(crate): the BfsInternal functions that misbehave with height < 3 or width >= 128 are no longer reachable outside the crate, only behind the dimension check of the public functions. No gas change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rng::draw_byte divides the pool by a NonZero<u8> bound with bounded_int::div_rem (1.10k vs 1.56k, and no conversion of the result); Rng::next_below and the spreader draws use it. Bits::top_byte and Bits::low_byte replace the DivRem by 2^120 and by 256 of the popcount and of the spreader select. Spreader -2 % to -5 % (max over the seeds), popcount -12.6 %, next_below -14 %, walker start -4.6 %. Same draws: no expectation changes. Measured and not kept: u8 by u8 (coords, parity, distance) costs the same with bounded_int. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One tile on a set of more than 8 is always a pick (30k-42k against a radix level and the table, 46k or more): the cost rule is skipped. The grid is checked on the limb that holds the end of the board (a POW128 lookup) instead of a u256 comparison with a converted power. Count 1: -6 % to -7 % mean, -5 % to -6 % max; every other count -0.6 % to -1.3 %. Same draws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The field loops receive the 4-value Dilation and the width instead of the layout: -0.1 % to -0.5 % on every field benchmark, the 3-class budget-2 case back to its L3 cost (134_645). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ctor Every benchmark more than 5 % cheaper than on main gets ceil(1.05 * measured) (77 budgets); the 10 spreader losers whose draws follow the new Rng stream get their new max over 32 seeds + 5 %. The lot sections of GAS.md get their measured and budget columns refreshed (their derived figures stay the lots' own); the new P1 section lists the promoted helpers, the Rng decisions and bounds, the measured losers, the per-unit costs of the generators, the CI time and the before/after of every library benchmark. The spreader trial microbenchmark draws with Rng::draw_byte like the library. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bal7hazar
force-pushed
the
refactor/hexmap-commons
branch
from
September 27, 2026 20:57
feee707 to
7f8214d
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lot P1 of
origami_hexmap: the helpers each lot re-implemented locally move to the shared files, every module uses them, the remaining gas is taken where it was measurable, and the hexmap CI job drops from 8m23s to under 4m20s (3m43s to 4m16s on the last runs, the L8 facade tests included).Shared primitives
helpers/bits.cairo:Bits::bitwise(AND, XOR and OR from one application of the builtin, wrapping the private corelib libfunc),Bits::and/or/xorper limb,Bits::popcountnow the L7 two-limb byte-count form,Bits::popcount_small,Bits::byte_counts,Bits::top_byte/low_byte(bounded_intdivisions), and the genericSet<T>of L3 (WideSet,SmallSet). The localextern fn bitwiseof caver, bfs, dial and their benches are gone.helpers/layout.cairo:Layout::expand/expand_smallrun the L1 dilation (limbs, bitwise triple, up/down fromX = 2P - Pewith one product each) through the new 4-valueDilationthat the layer loops carry;Layout::with_interior(3 shared lookups);Layout::edge_neighboursandLayout::neighbour_in, the edge-endpoint helpers ofBfsandDial.Caver::keep_componentfloods the frontier throughBfsInternal::component(the flood ofBfs::reachablewithout the checks): -5.6 % cave, -10.6 % maze, -11.5 % serpentine.helpers/rng.cairo: the pool refills below 2^64 (bias 2^-56 per pool instead of 2^-24, cost +0.04 % per carved tile);Rng::draw_byte,draw6,shuffle6andsplit216divide withcore::internal::bounded_int::div_rem(1.10k vs 1.56k). The walker draws 6 triples from each limb of every permutation. Keeping a spare pool or a refill counter inRngwas measured: +2 % per tile in the recursive generators (one more field), not kept.Gas (before =
mainat7adb9c4, 256 seeds for the spreader)next_below-14 %,Layout::expand-3.6 % (17x14), BFS layer step -6 %One library benchmark costs more:
bench_mazer_17x14_order_0+0.8 %, because the new stream carves 90 tiles instead of 89 (-0.3 % per tile).bench_rng_draw(genericu128bound) +0.4 %: one more refill per 100 draws with the 2^64 threshold.GAS.md(new section P1) has the before/after of every library benchmark, the measured losers and the bounds; 77 budgets are lowered.L8 facade (merged while this PR was open)
The branch is rebased on
eb0f4b1.map.cairocallsBfsInternal::and,expandandexpand_small: they remain as one-line delegations toBits::andandDilation, so the facade is untouched. Its benchmarks move with the libraries:compute_distribution-6.6 %, scenarios -2 % to -5 %,new_maze+0.8 % (the 90-tile maze); budgets intests/bench_map.cairoare left to L8.Visibility
The public traits keep their documented functions:
Mazer::generate,Digger::maze/corridor,Spreader::generate,Bfs::*,Dial::*,Caver::*,Walker::generate. The recursion, dig and selection helpers move topub(crate)internal impls;BfsInternal,Back,Endpoint, the stores and goals,Carver,Heading,TurnTrait,BitSetTraitandCountsbecomepub(crate). TheBfsInternalfunctions that misbehave with height < 3 or width >= 128 can no longer be reached from outside the crate.CI
The pull-request job runs
snforge test --package origami_hexmap --fuzzer-runs 64: the library fuzz benchmarks keep their budgets (max over 256 seeds) and check them on 64 seeds; the 100 spreader losers are#[ignore]d. A new non-blocking job,hexmap-full, runs everything with 256 seeds on pushes tomain(snforge test --package origami_hexmap --include-ignored). Locally, with a fresh build: 7m55s -> 2m46s.Expectations regenerated
The random stream changed (refill threshold, walker pools), so the exact grids of
test_mazer_generate_17x14_order_0/1,test_mazer_generate_19x13,test_digger_maze_order_0,test_walker_generate_17x14/7x7/19x13andbench_walker_17x14_504are regenerated (printouts included). The walker's scalar reference follows the new stream. No statistical or property test was loosened.🤖 Generated with Claude Code