The if (!dict.TryGetValue(k, out var list)) { list = []; dict[k] = list; } list.Add(v); pattern does two hash lookups per insert (TryGetValue + indexer set). CollectionsMarshal.GetValueRefOrAddDefault (net6+) collapses it into a single ref-returning lookup:
ref var list = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, k, out _);
list ??= [];
list.Add(v);
Sites (11 total across 5 files):
TUnit.Engine/Services/MetadataDependencyExpander.cs:115-120, 124-129, 132-137 (3 indexes built in one method, per discovery pass)
TUnit.Engine/Services/TestDependencyResolver.cs:30-37, 40-47 (per test registration)
TUnit.Engine/Services/TestGroupingService.cs:258-262, 264-268, 285-289 (per test grouping)
TUnit.Engine/Services/TestFinder.cs:45-50, 54-59 (per discovery)
TUnit.Engine/Building/Collectors/AotTestDataCollector.cs:131 (per test build)
Why hot: All sites run inside per-test or per-discovery loops; the dict-index-build pattern scales with test count.
TFM: CollectionsMarshal.GetValueRefOrAddDefault is net6+. TUnit.Engine targets net8.0+ — no gating needed.
The
if (!dict.TryGetValue(k, out var list)) { list = []; dict[k] = list; } list.Add(v);pattern does two hash lookups per insert (TryGetValue + indexer set).CollectionsMarshal.GetValueRefOrAddDefault(net6+) collapses it into a single ref-returning lookup:Sites (11 total across 5 files):
TUnit.Engine/Services/MetadataDependencyExpander.cs:115-120, 124-129, 132-137(3 indexes built in one method, per discovery pass)TUnit.Engine/Services/TestDependencyResolver.cs:30-37, 40-47(per test registration)TUnit.Engine/Services/TestGroupingService.cs:258-262, 264-268, 285-289(per test grouping)TUnit.Engine/Services/TestFinder.cs:45-50, 54-59(per discovery)TUnit.Engine/Building/Collectors/AotTestDataCollector.cs:131(per test build)Why hot: All sites run inside per-test or per-discovery loops; the dict-index-build pattern scales with test count.
TFM:
CollectionsMarshal.GetValueRefOrAddDefaultis net6+. TUnit.Engine targets net8.0+ — no gating needed.