Skip to content

Fix incremental compiler registration and cache wall-clock performance - #13

Merged
dannote merged 4 commits into
elixir-vibe:masterfrom
andreasronge:agent/fix-incremental-compiler
Aug 11, 2026
Merged

dannote merged 4 commits into
elixir-vibe:masterfrom
andreasronge:agent/fix-incremental-compiler

Conversation

@andreasronge

@andreasronge andreasronge commented Aug 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • register the documented compile.ex_dna Mix compiler task
  • replace the large per-file fragment cache with source digests plus complete clone results
  • return :noop with cached diagnostics when compiler inputs are unchanged
  • add mix ex_dna --cache so JSON/SARIF/HTML/console gates can use the same fast path with explicit paths
  • invalidate safely for same-timestamp edits, additions, removals, and output-shaping config changes
  • support compiler manifests, cleaning, and --force-ex_dna

Root cause

The compiler implementation lived at ExDNA.Compiler, so Mix could not resolve the documented :ex_dna compiler name to Mix.Tasks.Compile.ExDna.

After invoking the implementation directly, the old cache saved parsing but still deserialized and rewrote a large compressed AST/fragment term and reran global detection every time. On a real 578-file downstream gate, the cache grew to 49MB and made cold or changed runs slower than normal analysis.

This change treats the actual clone result as the reusable build artifact. Source digests make an unchanged result safe to reuse without depending on filesystem timestamp resolution. If anything changes, ExDNA runs its existing normal detector and replaces the small result cache.

Measured impact

PtcRunner's lib/ + test/ duplication scope (578 files, 79 clone groups), macOS, Elixir 1.20.2, OTP 29:

Run Wall clock Analysis time
Cold cached run 13.91s 13.08s
One added source 13.81s 12.79s
Unchanged warm run 1.49s 0.24s

The resulting cache is 87KB. Clone counts and JSON clone groups match the uncached report.

For comparison, v1.5.4's standalone analysis was 12.8–15.7s, while its warm compiler path remained 10.4–10.7s on the smaller default lib/ scope.

Validation

  • mix ci
    • format and warnings-as-errors compilation
    • strict Credo
    • 236 tests
    • Dialyzer
    • ExDNA duplication check
  • mix help compile.ex_dna
  • repeated JSON benchmark against PtcRunner's 578-file gate
  • same-mtime edit, removal, force-refresh, explicit-path JSON, and config-invalidation tests

Closes #12

Follow-up

A second, dependent performance PR is prepared on agent/sharded-fragment-cache. It adds a compact, generation-bound fingerprint index so exact clone-neutral edits can skip full-project analysis, extending this PR beyond the unchanged warm-cache case. The isolated two-commit delta is available in the fork comparison.

The follow-up is intentionally not opened against upstream master yet: doing so before this PR lands would duplicate this PR in its diff. It will be rebased and opened separately after this change is accepted. Its pinned candidate has already passed PtcRunner’s cold and warm ExDNA compatibility job in merged PtcRunner PR #1195.

The same pinned candidate compatibility job subsequently passed on PtcRunner PR #1196 and PtcRunner PR #1192.

Replace the costly fragment cache with source digests and cached clone results shared by the compiler and opt-in CLI analysis. Changed sources use normal full detection, while unchanged runs return the previous result without detection or cache rewrites.

Verified with mix ci and PtcRunner's 578-file duplication scope.
@andreasronge
andreasronge force-pushed the agent/fix-incremental-compiler branch from d7ef431 to 137bc5a Compare August 8, 2026 08:41
@andreasronge
andreasronge marked this pull request as ready for review August 8, 2026 15:32
@dannote
dannote merged commit 11fdb52 into elixir-vibe:master Aug 11, 2026
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.

Incremental compiler: compilers: ++ [:ex_dna] cannot resolve, and the cache gives no wall-clock speedup

2 participants