Skip to content

defk-o08.5: the report's hint search runs only under report: :full; DEFK_DUMP_C dumps each module's report - #71

Merged
DanielLuning merged 3 commits into
mainfrom
defk-o08.5/lazy-hints
Oct 20, 2026
Merged

DanielLuning merged 3 commits into
mainfrom
defk-o08.5/lazy-hints

Conversation

@DanielLuning

Copy link
Copy Markdown
Owner

Merge #70 first. This branch builds on defk-o08.4/stmt-reads-once, because both add entries to docs/performance.md. Until #70 merges, this PR shows #70's commit too.

What changed

For each kept bounds check, the fast-path report searched for a small fact that would drop it: the "(it would follow from w >= 0)" hint, from Facts.residual/5. The search took about 2.4% of compile time, and 6% on SatEx.Kernels, in every compile, whether or not anyone read the report.

  • The hint search runs only under use Defk, report: :full (the maintainer's choice). Defk.__before_compile__ passes hints: to Defk.Compiler.compile/4, which keeps it in the ctx. Without the option, a kept note ends at what nothing proves: x[i - w]: bounds check kept; nothing proves i - w < length(x).
  • Tests: the two test modules that read hints (condition_facts_test, product_facts_test) use report: :full. A new module, Defk.ConditionFactsTest.Plain, checks that the same kernel without the option keeps the plain note.
  • Docs: the report: :full option in the Defk moduledoc, docs/fast-path-report.md (the section is now "Hints and vectorisation"), docs/language.md (two places), and the Unreleased CHANGELOG.md entry that introduced hints. Hints have not shipped in a release, so that entry is corrected instead of adding a "Changed" line.
  • The gate tool: DEFK_DUMP_C now also writes <Module>.report, each module's report notes, beside <Module>.c. The same diff -r then checks the report too. docs/agents/runs.md describes it.
  • docs/performance.md 6.41: the result, and the two cuts tried first that keep every report the same, with the reasons they were not adopted:
    • A hint rendered only when its note survives saves 1.5% of the work but costs about 9% more time, because each kept note's closure keeps the env and the facts scope alive until the compile ends.
    • @hint_budget 8 already drops hints, and saves only 0.5%.

The branch has two commits of its own. The first records the two failed cuts and adds the report dump. The second makes the change.

Results

Measured with the DEFK_COMPILE_TIME harness, two interleaved rounds against #70's state:

  • Reductions: 114.9 M → 110.8 M (−3.6%; −1.2% without SatEx.Kernels, which alone saves 3.2 M).
  • Time: 932 → 922 ms (−1.1%, within drift).
  • The budget: against the compiler before the symbolic-bounds chain, the work is now +3.5% (−2.2% without SatEx.Kernels).
  • The C: unchanged. The two test modules that took report: :full differ only in their path-hashed defk:loop markers.
  • The reports: the same, less their hints. Two notes of HashChain.Kernels that differed only by their hints (two inline sites) are now kept once, as the report keeps any duplicate note once. PCM.Kernels keeps its hints, because it uses report: :full.

Provisional: the laptop was on battery, with no quiet-machine check.

How it was checked

  • mix ci on the laptop (macOS) passed: 2304 tests, Credo found no issues, Dialyzer reported 0 errors, every generated doc region up to date.

  • The gate: the C diff, and the report diff with the hints removed from the baseline.

  • Touches a promised surface? Yes: the public report: :full option now also turns on the hints. The Unreleased CHANGELOG.md entry that introduced hints says so. No deprecation is needed, because nothing is renamed or removed from a release.

  • Touches test/stability/? No.

Entering a statement computed its reads three times: live_after/1
(stmt_reads/1), the compiler's hoist/3 and Copies.enter_stmt/4 (reads/1,
the same set). Copies.block_liveness/1 keeps each statement's reads beside
its live set and enter/3 hands them on; live_after/1 and enter_stmt/4 stay.
C byte-identical; the compiler's work -8.6% (reductions), time -5.4%:
+7.4% of the work before the symbolic-bounds chain, under ADR-0007's
ceiling again (docs/performance.md 6.40).
…ch module's report

Neither way that keeps the report saves enough: a hint rendered only when
its note survives saves 1.5% of the work but costs ~9% time (each kept
note's closure holds the env and the facts scope until the compile ends);
@hint_budget 8 drops hints for -0.5%. Recorded in docs/performance.md
6.41; computing hints on demand changes __defk_report__/0 and is the
maintainer's call. The gate this needed stays: mix dump_c writes
<Module>.report beside <Module>.c, so the same diff checks the report.
Maintainer's call after the measurements of the previous commit: the
search for the fact that would drop a kept bounds check (Facts.residual/5)
runs only in a module with use Defk, report: :full (compile/4's hints
option, ctx.hints); otherwise the note ends at what nothing proves. The
two test modules that read hints use report: :full, and a kernel without
it keeps the plain note. Docs (report: :full, fast-path-report.md,
language.md, the Unreleased CHANGELOG entry that introduced hints) say so.
C unchanged; reports the same less their hints; -3.6% of the compiler's
work, +3.5% of the work before the symbolic-bounds chain
(docs/performance.md 6.41).
DanielLuning pushed a commit that referenced this pull request Oct 20, 2026
…26-10-20). Done on the branch (db0d8d0): -3.6% reductions, +3.5% of the work before step 1. PR #71, stacked on #70 (merge #70 first)."
@DanielLuning
DanielLuning merged commit 514ff6d into main Oct 20, 2026
2 checks passed
@DanielLuning
DanielLuning deleted the defk-o08.5/lazy-hints branch October 20, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant