Skip to content

v2.12.2: faster ClassProxy generation (index the resolver's classes once per build step) - #60

Merged
gmpassos merged 2 commits into
masterfrom
perf/generator
Oct 15, 2026
Merged

gmpassos merged 2 commits into
masterfrom
perf/generator

Conversation

@gmpassos

Copy link
Copy Markdown
Owner

Problem

To find the target class of a ClassProxy, InputAnalyzerResolved.findCandidateClassElements listed every library known to the resolver (thousands: the SDK and all the packages) and collected all their classes, then searched by name. It did this again for each ClassProxy.

In a project with 69 ClassProxys in one library, that library took 4.5s of the builder's ~7s of "building". About 3.7s of it went to collecting classes (~53ms per proxy, over ~2,400 libraries).

Fix

  • The resolver's classes are indexed by name once per build step (InputAnalyzerResolved), each library when it's first seen. The resolver gets more libraries as more are resolved (630 → 2,410 after the first proxy here), so each call still reads the resolver's current library list, at the same point as before, and indexes only the new ones.
  • The candidates are the same as before: the class sets are per library, so their union over the libraries is unchanged. The generated code is byte-for-byte identical (checked on the 75 generated files of that project).

Measured

Clean build_runner build of that project, local, on AC power, 2 runs each:

2.12.1 this PR
reflection_factory "building" 7s 4s
"analyzing" 4s 4s
Built with build_runner/aot in 23–24s 20s

What's left, for the record:

  • "analyzing" (~4s): the analyzer's first resolution of the program, shared by all inputs.
  • Compiling builders (~11s locally): build_runner's own cost; a trivial builder takes the same time.
  • Formatting (~1.5s) and the 225 @EnableReflection classes (~0.8s).

Also

  • CHANGELOG 2.12.1: don't name a private project.
  • Test: many ClassProxys in one library, the second with a libraryPath that brings in libraries the first one didn't index.
  • VM 565 and Chrome 439 tests pass; dart analyze --fatal-infos clean.

🤖 Generated with Claude Code

gmpassos and others added 2 commits October 15, 2026 03:59
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lassProxy lookup

findCandidateClassElements collected the classes of every resolver
library (thousands, SDK and packages included) for each ClassProxy.
They are now indexed by name once per build step, each library when
first seen (the resolver gets more libraries as more are resolved), so
the candidates are the same as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.55%. Comparing base (5e99421) to head (8023182).

Additional details and impacted files
@@           Coverage Diff           @@
##           master      #60   +/-   ##
=======================================
  Coverage   93.54%   93.55%           
=======================================
  Files          14       14           
  Lines        6538     6544    +6     
=======================================
+ Hits         6116     6122    +6     
  Misses        422      422           
Flag Coverage Δ
unittests 93.55% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gmpassos
gmpassos merged commit eb94ee8 into master Oct 15, 2026
5 checks passed
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