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 string was only used as a final null-coalescing fallback for DisplayName. Because TestMethod.DisplayName is always non-null (the constructor sets it to displayName ?? name), this allocation was thrown away on every call — 3× per test per run (discovery, in-progress, result).
AddTrxResultProperties had the same variable for two additional uses:
TrxTestDefinitionName(testMethod.DisplayName ?? testFullName) — DisplayName is never null, so the fallback never fired.
TryParseFullyQualifiedType(testFullName, ...) — re-parsed FullClassName from a string that already had FullClassName concatenated into it. testMethod.FullClassName is directly available.
Changes
CreateBaseTestNode: inline testFullName into the null-coalescing chain; the compiler only evaluates the interpolation if both prior operands are null (they never are).
AddTrxResultProperties: use testMethod.DisplayName directly for TrxTestDefinitionName; use testMethod.FullClassName directly in the testMethodIdentifierProperty-absent fallback path; remove the now-dead TryParseFullyQualifiedType private method.
Performance Evidence
For a 10 000-test suite:
Eliminated: ~30 000 eager string allocations in CreateBaseTestNode (3 calls × 10 000 tests; each string ≈ 50–100 chars of Namespace.ClassName.MethodName)
Eliminated: 1 string allocation per TRX-result test node in the testMethodIdentifierProperty-absent path
Eliminated: string parse work in TryParseFullyQualifiedType for that fallback path (2× LastIndexOf, substring slice)
These are transient allocation savings; GC collection and throughput impact is proportional to test-suite size.
Trade-offs
None. DisplayName is documented as always initialized; FullClassName is the source of truth for the type name. Behavior is identical.
Test Status
MSTest.TestAdapter (net9.0) builds cleanly with 0 warnings and 0 errors. MSTestTestNodeConverter unit tests (24 tests) could not be run locally due to framework restore failures in this environment (unrelated pre-existing issue: NU1201 for net48/net462 targets); CI will verify.
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
southcentralus0.in.applicationinsights.azure.com
To allow these domains, add them to the network.allowed list in your workflow frontmatter:
🤖 Automated content by GitHub Copilot. Generated by the Perf Improver workflow. · 301.7 AIC · ⌖ 15.9 AIC · ⊞ 12.5K · [◷]( · ◷)
Add this agentic workflows 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/lazy-testfullname-allocation-7012a5b3d6ba4693.
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 preview (106 of 106 lines)
From d82c12d7e7da1153824753b87198613ccfd940ce Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Fri, 10 Jul 2026 14:32:08 +0000
Subject: [PATCH] perf: eliminate eager testFullName allocation in
MSTestTestNodeConverter
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In CreateBaseTestNode, the string `testFullName` was always computed
eagerly even though it is only needed as a final fallback when both
`displayNameOverride` and `testMethod.DisplayName` are null. Since
`TestMethod.DisplayName` is always initialized (constructor sets it
to `displayName ?? name`), the allocation is never used. Inline the
interpolation so the compiler only evaluates it if the earlier operands
are null.
In AddTrxResultProperties, `testFullName` was used in three places:
- TrxTestDefinitionName fallback: `testMethod.DisplayName` is always
non-null, so the fallback never fired; use `testMethod.DisplayName`
directly.
- TrxFullyQualifiedTypeNameProperty fallback: the only use was to parse
back the class name that is already present as `testMethod.FullClassName`;
use it directly and remove the now-dead `TryParseFullyQualifiedType`
private method.
For a 10 000-test suite this eliminates ~30 000 transient string
allocations per run in CreateBaseTestNode (3 calls per test ×
FullClassName + '.' + MethodName string), plus one additional string
allocation per TRX-result test node in the fallback path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../MSTestTestNodeConverter.cs | 29 ++-----------------
1 file changed, 3 insertions(+), 26 deletions(-)
diff --git a/src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestTestNodeConverter.cs b/src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestTestNodeConverter.cs
index 001a3d9..8e2486f 100644
--- a/src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestTestNodeConverter.cs+++ b/sr
... (truncated)
Goal and Rationale
MSTestTestNodeConverter.CreateBaseTestNodeeagerly computed:This string was only used as a final null-coalescing fallback for
DisplayName. BecauseTestMethod.DisplayNameis always non-null (the constructor sets it todisplayName ?? name), this allocation was thrown away on every call — 3× per test per run (discovery, in-progress, result).AddTrxResultPropertieshad the same variable for two additional uses:TrxTestDefinitionName(testMethod.DisplayName ?? testFullName)—DisplayNameis never null, so the fallback never fired.TryParseFullyQualifiedType(testFullName, ...)— re-parsedFullClassNamefrom a string that already hadFullClassNameconcatenated into it.testMethod.FullClassNameis directly available.Changes
CreateBaseTestNode: inlinetestFullNameinto the null-coalescing chain; the compiler only evaluates the interpolation if both prior operands are null (they never are).AddTrxResultProperties: usetestMethod.DisplayNamedirectly forTrxTestDefinitionName; usetestMethod.FullClassNamedirectly in thetestMethodIdentifierProperty-absent fallback path; remove the now-deadTryParseFullyQualifiedTypeprivate method.Performance Evidence
For a 10 000-test suite:
CreateBaseTestNode(3 calls × 10 000 tests; each string ≈ 50–100 chars ofNamespace.ClassName.MethodName)testMethodIdentifierProperty-absent pathTryParseFullyQualifiedTypefor that fallback path (2×LastIndexOf, substring slice)These are transient allocation savings; GC collection and throughput impact is proportional to test-suite size.
Trade-offs
None.
DisplayNameis documented as always initialized;FullClassNameis the source of truth for the type name. Behavior is identical.Test Status
MSTest.TestAdapter(net9.0) builds cleanly with 0 warnings and 0 errors.MSTestTestNodeConverterunit tests (24 tests) could not be run locally due to framework restore failures in this environment (unrelated pre-existing issue:NU1201fornet48/net462targets); CI will verify.Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
southcentralus0.in.applicationinsights.azure.comSee Network Configuration for more information.
Add this agentic workflows 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/lazy-testfullname-allocation-7012a5b3d6ba4693.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 preview (106 of 106 lines)