perf: memoize type resolution; skip and source-generate JSON work - #51
Merged
Conversation
…te JSON work GetTypeByMetadataName walks assemblies on every call, and the transforms resolved the same handful of names per field per class per compilation - tens of thousands of walks per keystroke at corpus scale. A per-compilation ConditionalWeakTable + ConcurrentDictionary cache collapses every call site (53) to a dictionary hit, including the migration augment stage's arbitrary schema type names. The augment stage also skips resolution entirely for properties without a save flag, since the value-type fact only affects the nullable suffix on save-flagged content struct fields. Migration JSON parsing and schema writing use a source-generated JsonSerializerContext, removing reflection-based metadata construction from the analyzer process. Benchmarks (150 classes): cold full run 29.9ms -> 6.5ms (3.2x faster than even the pre-#49 pipeline's 20.7ms), single-edit warm re-run 47.9ms -> 19.6ms, no-change re-run unchanged at ~64us. Output proven neutral: all snapshots byte-identical and the 3,786-source corpus manifest is unchanged. Co-Authored-By: Claude Fable 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.
Summary
Follow-up perf pass on the incremental pipeline, targeting the transform layer that #49 made the entire per-edit cost.
GetTypeByMetadataNamewalks assemblies on every call, and the transforms resolve the same handful of names per field per class per compilation — tens of thousands of walks per keystroke at corpus scale. AConditionalWeakTable<Compilation, ConcurrentDictionary<...>>cache collapses all 53 call sites to dictionary hits (weakly keyed so discarded compilations don't pin symbols). This also covers the migration augment stage's arbitrary schema type names for free.JsonSerializerContext, removing reflection-based serializer metadata construction from the analyzer process.Numbers (150-class corpus with migrations)
The cold run is now 3.2× faster than even the pre-#49 pipeline (20.7 ms), erasing the cold-build trade-off #49 accepted; the per-edit cost drops another 2.4×.
Proof
89/89 tests green with every snapshot byte-identical; the 3,786-source real-corpus manifest is unchanged; the 150-class probe still shows
SourceOutput: executed=0after an inert edit.🤖 Generated with Claude Code