perf(analyzers): cache test framework discovery per compilation - #98
Conversation
FindAwakeFrameworks re-ran TestMethodDiscovery.FindTestMethods, a full syntax-tree walk, for every other registered test framework on every Execute call, with no caching between analyzer instances. A project awake on N frameworks at once (dual xUnit versions being the ordinary case, not an exotic one) therefore paid for roughly N times more discovery walks than necessary, none of them shared across the analyzers that all asked the same question about the same compilation. Memoize FindTestMethods results per (Compilation, probe type) using the same ConditionalWeakTable<Compilation, ConcurrentDictionary<Type, ImmutableArray<IMethodSymbol>>> pattern already used for the tests-without-production-reference cache. Each framework's discovery now runs at most once per compilation, however many awake frameworks end up asking for it. The outer table is keyed by Compilation and evicted by the garbage collector together with it; the inner ConcurrentDictionary keeps two racing analyzers from computing the same entry twice. Behavior is unchanged, this is a pure performance fix. Adds unit tests covering the new cache: a hit across repeated calls for the same compilation and framework, independent results per framework, independent results per compilation, and the two-framework scenario the fix targets, where a later analyzer reuses an earlier one's discovery walk instead of repeating it.
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #98 +/- ##
=======================================
Coverage 95.26% 95.26%
=======================================
Files 88 88
Lines 5850 5854 +4
Branches 1273 1274 +1
=======================================
+ Hits 5573 5577 +4
Misses 122 122
Partials 155 155 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Summary
FindAwakeFrameworksinTestSurfaceAnalysisre-ranTestMethodDiscovery.FindTestMethods— a full syntax-tree walk — for every other registered test framework on every analyzerExecutecall, with no caching between analyzer instances.FindTestMethodsresults per(Compilation, probe type), using the sameConditionalWeakTable<Compilation, ConcurrentDictionary<Type, ImmutableArray<IMethodSymbol>>>pattern already used for the tests-without-production-reference cache a few lines above. Each framework's discovery now runs at most once per compilation regardless of how many analyzer instances query it. This is a pure performance fix; behavior is unchanged.Test plan
TestSurfaceAnalysisTestMethodCacheTestscovering: cache hit across repeated calls for the same compilation and framework, independent results per framework, independent results per compilation, and the two-framework scenario the fix targets (a later analyzer reusing an earlier one's discovery walk instead of repeating it).dotnet test ./Frameshift.slnxpasses across all target frameworks (29392 tests, 0 failed).dotnet csharpier format .run; working tree clean of formatting diffs.