Repository navigation
defk-w8l: one countdown for the safepoint budget instead of two counters - #81
Merged
Merged
Conversation
…two arguments bounds the later one A gather loop (bench/gather_layer.exs) lists the checks its hot loop keeps. Most of the handwired study's list was already proven away; one was not for a reason of ranking: facts land on a condition's newest atom, and parameters ranked by their C names, so base <= length(x) bounded the length and not base, and base + idx[j] kept its overflow check. The facts scope now carries the parameters' declaration order, and the ranking (newest/2, the product's canonical form) reads it; a scope without one still ranks by name (the unit tests' scopes). The gate shows one module changed, which lost a range-limit test; the guarded gather loop runs about 0.75 ns per term where it was 0.9-1.1; the compiler does +0.5% of its work. Recorded as docs/performance.md 6.45; the rule for users in docs/language.md (raising guards).
The yield bookkeeping of a kernel kept two values live, the tick count and the budget; a safepoint now counts one value down from the budget and tests it against zero, and the budget lives in the clock, where defk_tick keeps it anyway. Same semantics (ticks >= budget is budget - ticks <= 0; a resume restores the saved budget). Measured (docs/performance.md 6.46): fuzzy_search's per-word gap to its yield: false twin falls from +30% to +16%; Keccak's round loop is unchanged (12 spills per round, 1.3x), and the entry shows why: 8 of its 12 spills are the safepoint's saves and 3 the resume dispatch, none the counters. Two other variants (charge a plain short loop on entry; no bookkeeping register at all) gained nothing and are recorded. bench/keccak_yield.exs counts the spills and times 16 MB; the tick gap and the test suite are unchanged.
DanielLuning
pushed a commit
that referenced
this pull request
Oct 22, 2026
…one countdown instead of two counters; fuzzy_search +30% -> +16%, Keccak unchanged (its 12 spills are the saves (8) and the resume dispatch (3), not the counters; 1.3x quiet). Variants V2 (charge on entry) and V3 (no bookkeeping register) measured, not adopted. Tick gap unchanged, mix ci green. docs/performance.md 6.46. Stays in progress until the merge."
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.
What changed
Stacked on #80 (defk-w8r.3), which is stacked on #79: merge #79, then #80, then this.
The yield bookkeeping of a kernel kept two values live, the tick count and the budget. A safepoint now counts one value down from the budget and tests it against zero (
DEFK_SP,DEFK_TICKSinsp_macro/3; the preamble inrun_preamble/1); the budget lives only in the clock (defk_clk.budget), wheredefk_tickkeeps it anyway. Same semantics:ticks >= budgetisbudget - ticks <= 0, and a resume restores the saved budget as before. The header's interface list losesdefk_budget. No runtime header code changed.A new bench,
bench/keccak_yield.exs, compilesexamples/keccak.exs' kernels twice (yielding,yield: false), counts the stack loads and stores in the hottest round block of the assembly (cc -Swith the build's flags, cut at the loop's back-edge), and times one 16 MB message interleaved. The breakdowns aredocs/performance.md6.46; 6.4 and 6.8 point at it.Results
bench/yield_cost.exs, 12 schedulers, 20 queries x 5 rounds): the per-word gap to theyield: falsetwin goes from +30-31% (three runs) to +16-17% (three runs), about 5 ns to 3 ns per word on 17.yield: falseshape); the counters are none of the 12. A redesign of the saves or the dispatch is out of this ticket's scope and is noted as such.envin the clock): Keccak unchanged, fuzzy_search +19.6%, the memory read-modify-write per word costs more than the register it frees.bench/tick_gap.exs, 3 runs a side): the yielding kernel's p99 2.27 ms against 2.25 onmain, worst 2.3-2.5 against 2.3; unchanged.How it was checked
mix cion the M-series laptop: 2309 passed, 817 excluded (forced-yield tests included);mix testonce more before the ci run.test/runtime_interface_test.exspasses with the shortened interface list.CHANGELOG.mdentry.test/stability/? No.Adoption rule
The ticket asked for a change to be adopted only when spills drop and time improves beyond noise on both Keccak and fuzzy_search. The countdown meets it on fuzzy_search (three runs each side) and explains Keccak without changing it. Adopting it anyway is this PR's proposal, as it simplifies the bookkeeping and loses nothing; owner's call.