You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 BuildLogEntry → GetUpperCaseName, 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.
To fix the permissions issue, go to Settings → Actions → General 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
Goal and Rationale
The
InternalSyncLogmethod inFileLoggerused{logLevel}directly in an interpolated string:This calls
Enum.ToString()on every log entry — boxing theLogLevelenum 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
BuildLogEntry→GetUpperCaseName, which returns a cached interned literal ("DEBUG","WARNING", etc.) with zero allocation.GetUpperCaseNamewas added specifically to fix this pattern (see the comment in the method).Approach
Apply
GetUpperCaseName(logLevel)inInternalSyncLogto match the async path. The existingGetUpperCaseNamehelper already handles allLogLevelvalues.Performance Evidence
Before:
{logLevel}→Enum.ToString()→ boxes enum + allocates string per log entryAfter:
GetUpperCaseName(logLevel)→ returns interned literal, zero allocation per log entryThe 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 asyncBuildLogEntry), 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.
Add this agentic workflow to your repo
To install this agentic workflow, run
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 Settings → Actions → General 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