From 0c1f89598c64a80eda69ba6eb22be1721aa3abd4 Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Thu, 28 May 2026 21:05:44 +0100 Subject: [PATCH] perf: drop LINQ join and bool double-alloc in TestNameFormatter FormatArguments built a temporary string[] via Select and materialized it through string.Join's IEnumerator; replace with a direct loop into a pooled StringBuilder, avoiding the iterator, closure and intermediate array. FormatArgumentValue formatted bool via b.ToString().ToLowerInvariant(), which allocates twice; use the interned 'true'/'false' literals instead. Output is byte-identical (lowercase) in both cases. Closes #6030 Closes #6031 --- TUnit.Core/Services/TestNameFormatter.cs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/TUnit.Core/Services/TestNameFormatter.cs b/TUnit.Core/Services/TestNameFormatter.cs index 3c6f108090..83dc031630 100644 --- a/TUnit.Core/Services/TestNameFormatter.cs +++ b/TUnit.Core/Services/TestNameFormatter.cs @@ -51,7 +51,7 @@ public string FormatArgumentValue(object? value) null => "null", string str => $"\"{str}\"", char ch => $"'{ch}'", - bool b => b.ToString().ToLowerInvariant(), + bool b => b ? "true" : "false", // Use InvariantCulture for numeric types to avoid culture-specific formatting issues double d => d.ToString(System.Globalization.CultureInfo.InvariantCulture), float f => f.ToString(System.Globalization.CultureInfo.InvariantCulture), @@ -95,7 +95,26 @@ private string FormatArguments(object?[] args) return string.Empty; } - return string.Join(", ", args.Select(FormatArgumentValue)); + // Build directly into a pooled StringBuilder to avoid the LINQ iterator/closure + // and the temporary string[] that Select + string.Join would materialize. + var builder = StringBuilderPool.Get(); + try + { + for (var i = 0; i < args.Length; i++) + { + if (i > 0) + { + builder.Append(", "); + } + builder.Append(FormatArgumentValue(args[i])); + } + + return builder.ToString(); + } + finally + { + StringBuilderPool.Return(builder); + } } private string FormatEnumerable(IEnumerable enumerable)