From 31cad400d43d281a485808f58edf603e9739c177 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Thu, 28 May 2026 18:14:23 +0100 Subject: [PATCH] perf(engine): avoid closure allocation in AfterHookPairTracker.GetOrCreateAfterAssemblyTask (#6041) Add a lock-free TryGetValue fast path before GetOrAdd so cache hits no longer allocate a closure capturing taskFactory. Mirrors the existing pattern in GetOrCreateAfterClassTask. --- TUnit.Engine/Services/AfterHookPairTracker.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/TUnit.Engine/Services/AfterHookPairTracker.cs b/TUnit.Engine/Services/AfterHookPairTracker.cs index 2adc97a56b..9f25689412 100644 --- a/TUnit.Engine/Services/AfterHookPairTracker.cs +++ b/TUnit.Engine/Services/AfterHookPairTracker.cs @@ -155,6 +155,12 @@ public ValueTask> GetOrCreateAfterTestSessionTask(Func public ValueTask> GetOrCreateAfterAssemblyTask(Assembly assembly, Func>> taskFactory) { + // Lock-free fast path avoids allocating a closure on the common cache-hit case. + if (_afterAssemblyTasks.TryGetValue(assembly, out var existingTask)) + { + return new ValueTask>(existingTask); + } + var task = _afterAssemblyTasks.GetOrAdd(assembly, a => taskFactory(a).AsTask()); return new ValueTask>(task); }