-
-
Notifications
You must be signed in to change notification settings - Fork 108
Closed
Description
Parent Epic
Part of #4159 - Performance Optimization: Hot Path Improvements
Problem
LINQ methods (.Any(), .Where(), .OrderBy(), .Select().ToArray()) allocate iterator objects and intermediate collections on every call. In hot paths executed per-test, this creates GC pressure proportional to test count.
Evidence
| File | Lines | Pattern | Impact |
|---|---|---|---|
TUnit.Engine/Scheduling/ConstraintKeyScheduler.cs |
59, 165 | .Any() inside lock |
Per-constrained-test |
TUnit.Engine/Scheduling/TestScheduler.cs |
174 | .OrderBy() in foreach |
Per-test-group |
TUnit.Engine/Services/EventReceiverOrchestrator.cs |
248, 262 | .OrderBy() during dispatch |
Per-test-event |
TUnit.Engine/Discovery/ReflectionTestDataCollector.cs |
361, 490, 522-530 | .Where().ToArray() |
Per-type during discovery |
TUnit.Engine/Building/TestBuilder.cs |
157, 215, 697, 1108-1110 | .Any(), .Select().ToList() |
Per-test-build |
TUnit.Engine/Services/HookCollectionService.cs |
555-557, 581-583 | .OrderBy().Select().ToList() |
Per-class hooks |
Suggested Approach
Replace LINQ with manual loops. Example transformation:
// Before
canStart = !constraintKeys.Any(key => lockedKeys.Contains(key));
// After
var canStart = true;
foreach (var key in constraintKeys)
{
if (lockedKeys.Contains(key)) { canStart = false; break; }
}// Before
foreach (var kvp in group.Value.OrderBy(t => t.Key))
// After
var sorted = new List<KeyValuePair<int, T>>(group.Value);
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
foreach (var kvp in sorted)Verification
- Run
TUnit.PerformanceBenchmarksat 10k scale before changes - Apply LINQ elimination changes
- Run benchmarks again, compare total time and GC counts
- Use
dotnet-traceallocation profiling to verify reduced allocations
Risks
- Low risk - straightforward mechanical transformation
- Ensure loop logic matches LINQ semantics exactly (early exit for
.Any(), stable sort for.OrderBy())
Priority
P0 - Quick wins with low risk, high impact on per-test allocations
Metadata
Metadata
Assignees
Labels
No labels