Skip to content

[perf-improver] perf: use GetUpperCaseName in InternalSyncLog to avoid Enum.ToString() allocation #10261

Description

@github-actions

Goal and Rationale

The InternalSyncLog method in FileLogger used {logLevel} directly in an interpolated string:

_writer.WriteLine($"[{_clock.UtcNow.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture)} {category} - {logLevel}] {formatter(state, exception)}");

This calls Enum.ToString() on every log entry — boxing the LogLevel enum value and allocating a new string on the heap for each log line written on the sync-flush path.

The async/enqueue paths already route through BuildLogEntryGetUpperCaseName, which returns a cached interned literal ("DEBUG", "WARNING", etc.) with zero allocation. GetUpperCaseName was added specifically to fix this pattern (see the comment in the method).

Approach

Apply GetUpperCaseName(logLevel) in InternalSyncLog to match the async path. The existing GetUpperCaseName helper already handles all LogLevel values.

Performance Evidence

Before: {logLevel}Enum.ToString() → boxes enum + allocates string per log entry
After: GetUpperCaseName(logLevel) → returns interned literal, zero allocation per log entry

The fix is in a log entry formatter, which is called once per log line. In verbose (--diagnostic) runs, this can be thousands of calls per test session.

Trade-offs

None. This is strictly an optimization — same behavior, same output format, no functional change.

Note: the sync-flush path uses "HH:mm:ss.fff" format (not the ISO 8601 "O" format used by the async BuildLogEntry), so the two paths produce slightly different timestamps. This PR intentionally preserves the existing format on the sync path.

Test Status

Build infrastructure requires the .NET 11 preview SDK (not available in this environment). The change is a mechanical one-liner following the established pattern in the same file — reviewed by code inspection. CI will validate.

🤖 Automated content by GitHub Copilot. Generated by the Perf Improver workflow. · sonnet46 202.9 AIC · ⌖ 15 AIC · ⊞ 13.1K · [◷]( · )
Comment /perf-assist to run again

Add this agentic workflow to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/perf-improver.md@main

Note

This was originally intended as a pull request, but GitHub Actions is not permitted to create or approve pull requests in this repository.
The changes have been pushed to branch perf-assist/sync-log-upper-case-name-7276a50ff1b3ad98.

Click here to create the pull request

To fix the permissions issue, go to SettingsActionsGeneral and enable Allow GitHub Actions to create and approve pull requests. See also: gh-aw FAQ

Show patch (39 lines)
From aa40d1610ac2359e6a65f8d6059a96f086452118 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Mon, 27 Jul 2026 14:22:10 +0000
Subject: [PATCH] perf: use GetUpperCaseName in InternalSyncLog to avoid
 Enum.ToString() allocation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The sync-flush log path (InternalSyncLog) used {logLevel} directly in an
interpolated string, which calls Enum.ToString() — boxing the enum and
allocating a string on every log entry.

The async/queue paths already route through BuildLogEntry + GetUpperCaseName,
which returns an interned literal instead. Apply the same pattern to the
sync-flush path for consistency and to eliminate the per-entry allocation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
 src/Platform/Microsoft.Testing.Platform/Logging/FileLogger.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Platform/Microsoft.Testing.Platform/Logging/FileLogger.cs b/src/Platform/Microsoft.Testing.Platform/Logging/FileLogger.cs
index 313ff81..4016f29 100644
--- a/src/Platform/Microsoft.Testing.Platform/Logging/FileLogger.cs
+++ b/src/Platform/Microsoft.Testing.Platform/Logging/FileLogger.cs
@@ -196,7 +196,7 @@ private void InternalSyncLog<TState>(LogLevel logLevel, TState state, Exception?
 
         try
         {
-            _writer.WriteLine($"[{_clock.UtcNow.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture)} {category} - {logLevel}] {formatter(state, exception)}");
+            _writer.WriteLine($"[{_clock.UtcNow.ToString("HH:mm:ss.fff", CultureInfo.InvariantCulture)} {category} - {GetUpperCaseName(logLevel)}] {formatter(state, exception)}");
         }
         finally
         {
-- 
2.54.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions