Skip to content

Enable multithreaded MSBuild for local and PR builds - #10726

Draft
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded
Draft

Enable multithreaded MSBuild for local and PR builds#10726
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded

Conversation

@JanProvaznik

@JanProvaznikJan Provazník (JanProvaznik) commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • enable MSBuild's experimental multithreaded mode by default for local builds
  • enable multithreaded MSBuild explicitly in ordinary public/PR Azure Pipelines builds on Windows, Linux, and macOS
  • keep MSBuildCache graph/cache follow-up builds process-based
  • keep the official build pipeline unchanged

Local benchmark

Measured five clean-output restore+build runs per mode after warming the SDK, workload, and NuGet caches on an 8-core/16-logical-processor Windows machine.

ModeRunsAverageMedianRange
Existing process-based MSBuild5167.1s166.6s154.1–181.9s
Multithreaded MSBuild5159.0s160.7s144.2–168.3s

Local average improved by 8.1 seconds (4.8%) and median by 5.9 seconds (3.6%). The ranges overlap, so this is directional rather than statistically conclusive.

CI benchmark

Azure Pipelines build 1566758 succeeded in every configuration. The baseline is the average build-step duration from the four most recent successful fork PR builds (1566681, 1564881, 1564777, and 1564593), which use the same cache-disabled fallback path and are therefore more comparable than trusted-branch cache builds.

Build stepMultithreadedFork PR baselineChange
Windows Debug666.1s715.0s-6.8%
Windows Release685.5s692.4s-1.0%
Linux Debug367.1s367.1s0.0%
Linux Release352.1s369.5s-4.7%
macOS Debug663.0s702.8s-5.7%
macOS Release513.3s850.6s-39.7%

The two Windows configurations improved from 703.7s to 675.8s combined (-4.0%), closely matching the 4.8% local average improvement. Linux is neutral-to-modestly faster. macOS is highly variable—the baseline samples range from 533.7s to 1,015.6s for Debug and 723.9s to 1,021.9s for Release—so the apparent Release gain should not be treated as a reliable estimate.

MSBuildCache compatibility finding

The first experiment, build 1566674, failed because the cache-disabled Windows fallback still imported Microsoft.MSBuildCache.SharedCompilation. Its unannotated ResolveFileAccesses task was routed to a sidecar TaskHost under -mt. MSBuild then corrupted the returned FileAccessData structs during TaskHost packet deserialization through interface boxing and crashed in FileAccessManager.ReportFileAccess when replaying a null path.

The ProjectCachePlugin itself was inactive, so this was not a cache lookup or materialization race. The engine defect is tracked by dotnet/msbuild#14824.

This PR therefore keeps cache graph and cache-specific sign/pack operations process-based. Ordinary Windows fallback builds use -mt without importing cache support packages; Linux and macOS ordinary builds also use -mt.

Conclusion

Multithreaded MSBuild provides a modest end-to-end improvement on Windows: 4.8% locally and 4.0% in comparable PR CI, with no corrected-run failures. Linux results are consistent with a smaller improvement, while current macOS variance is too high for a precise estimate. Cache population and multithreaded execution should remain separate experiments until the TaskHost file-access serialization defect is fixed and their combined topology can be evaluated independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI balanced review requested due to automatic review settings August 25, 2026 11:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables multithreaded MSBuild for local Windows builds and public CI builds while leaving official builds unchanged.

Changes:

  • Defaults local PowerShell builds to multithreaded mode.
  • Enables multithreading across public Windows, Linux, and macOS CI paths.
  • Identified missing equivalent default for local Unix builds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
eng/build.ps1Configures the local PowerShell default.
azure-pipelines.ymlEnables multithreading in public CI build paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadeng/build.ps1
Comment on lines +86 to +87
if (-not $PSBoundParameters.ContainsKey("msbuildMultiThreaded")) {
$PSBoundParameters["msbuildMultiThreaded"] = -not $ci
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Build Failure Analysis

Summary — Enabling MSBuild's new -msbuildMultiThreaded (-mt) mode in this PR triggers a NullReferenceException inside the ResolveFileAccesses MSBuild task shipped by the Microsoft.MSBuildCache.SharedCompilation package, failing every Windows build leg (Release and Debug); the Linux/macOS legs (which don't hit this code path) compiled cleanly.

Root cause: -mt is incompatible with Microsoft.MSBuildCache.SharedCompilation's ResolveFileAccesses task

This PR adds -msbuildMultiThreaded/-mt to the CI invocations in azure-pipelines.yml and threads the corresponding parameter through eng/build.ps1. On both Windows Release and Windows Debug legs, MSBuild fails 13 projects (e.g. Microsoft.Testing.Platform, TestFramework.SourceGeneration, TestFramework, MSTest.Analyzers, MSTest.SourceGeneration, MSTest.Sdk) with the identical stack:

MSB4018: The "ResolveFileAccesses" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Build.FileAccesses.FileAccessManager.ReportFileAccess(FileAccessData fileAccessData, Int32 nodeId)
at Microsoft.Build.BackEnd.TaskHostTask.HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
at Microsoft.Build.BackEnd.TaskHostTask.HandlePacket(INodePacket packet, Boolean& taskFinished)
at Microsoft.Build.BackEnd.TaskHostTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9 in the ResolveCoreCompileFileAccesses target of the restored .packages\microsoft.msbuildcache.sharedcompilation\0.1.328-preview package. This repo already uses that MSBuildCache package for shared/out-of-proc compilation, which relies on MSBuild's TaskHostTask/FileAccessManager file-access-reporting plumbing (used for build-output caching). Turning on -mt changes MSBuild's node/threading model for concurrent task execution and file-access reporting; FileAccessManager.ReportFileAccess null-refs when it receives a completion callback for a node id it apparently doesn't have registered under multi-threaded execution — an incompatibility between this MSBuildCache version's file-access hook and -mt mode, not a defect in TestFx's own source.

Evidence that isolates -mt as the trigger:

  • Only the Windows legs that pass -msbuildMultiThreaded:$true/-mt (Windows Release, Windows Debug) fail; the Windows application-model acceptance leg, both Linux legs, and both macOS legs built cleanly.
  • Every failing project fails at the exact same target/task/line (ResolveCoreCompileFileAccessesResolveFileAccesses, SharedCompilation.targets:9) — one root cause fanning out across 13 projects, not 13 independent bugs.
  • No C#/analyzer compiler errors were reported anywhere in either failing leg — the actual compile never runs; the crash happens in the file-access-tracking wrapper around the compile task itself.

Affected projects (13 total, identical stack; representative subset)

  • src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
  • src/Platform/Microsoft.Testing.Platform.ServerMode.Client.Sources/...csproj
  • src/TestFramework/TestFramework.SourceGeneration/TestFramework.SourceGeneration.csproj
  • src/TestFramework/TestFramework/TestFramework.csproj (Debug leg only)
  • src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
  • src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj
  • src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj
  • src/Package/MSTest.Sdk/MSTest.Sdk.csproj
  • test/IntegrationTests/TestAssets/SampleProjectForAssemblyResolution/...csproj
  • samples/CtrfPlayground/XunitMtp/XunitMtp.csproj

Suggested fix

This is a build-infrastructure/tooling incompatibility, not a TestFx source-code bug, so it falls outside this workflow's automated fix-commit scope (limited to src//test/; eng/build.ps1 and azure-pipelines.yml are both excluded, and the fix is not a mechanical rename provable from a compiler error anyway). Two viable directions for a maintainer:

  1. Don't enable -mt on legs where Microsoft.MSBuildCache.SharedCompilation is active until that package (currently pinned at 0.1.328-preview) ships a fix for -mt compatibility — i.e. drop the newly-added -msbuildMultiThreaded lines for the Windows Release/Debug stages in azure-pipelines.yml, or gate them behind whether MSBuildCache is enabled for that leg.
  2. If -mt is required for this PR's goal, file/check for an upstream issue against Microsoft.MSBuildCache for -mt (multi-threaded node) compatibility with its ResolveFileAccesses/FileAccessManager file-access-tracking hook, and bump the package once fixed.

Since the crash originates inside a third-party MSBuild extension package rather than TestFx source, no inline code suggestion is offered — reverting or gating the newly-added -mt flags on the affected legs is the pragmatic short-term mitigation.


Build overview (Windows Release leg)
Build: FAILED
Duration: 156.2s
MSBuild: 18.10.0-1.26379.9+c88db8eb0
Projects: 74 Errors: 13 Warnings: 1
All MSBuild errors (13, identical across Windows Release + Windows Debug legs)
CodeTaskTargetRoot message
MSB4018ResolveFileAccessesResolveCoreCompileFileAccessesNullReferenceException in FileAccessManager.ReportFileAccess, thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9

(13 occurrences across each failing leg, one per failed project, all sharing this identical stack trace.)


🤖 Generated by the Build Failure Analysis workflow using (a href="(dev.azure.com/redacted) · commit ca552a2

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · auto · 92.4 AIC · ⌖ 1.74 AIC · ⊞ 13.3K · [◷]( · )

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 25, 2026 12:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JanProvaznik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Enable multithreaded MSBuild for local and PR builds by JanProvaznik · Pull Request #10726 · microsoft/testfx · GitHub
Skip to content

Enable multithreaded MSBuild for local and PR builds - #10726

Draft
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded
Draft

Enable multithreaded MSBuild for local and PR builds#10726
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded

Conversation

@JanProvaznik

@JanProvaznikJan Provazník (JanProvaznik) commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • enable MSBuild's experimental multithreaded mode by default for local builds
  • enable multithreaded MSBuild explicitly in ordinary public/PR Azure Pipelines builds on Windows, Linux, and macOS
  • keep MSBuildCache graph/cache follow-up builds process-based
  • keep the official build pipeline unchanged

Local benchmark

Measured five clean-output restore+build runs per mode after warming the SDK, workload, and NuGet caches on an 8-core/16-logical-processor Windows machine.

ModeRunsAverageMedianRange
Existing process-based MSBuild5167.1s166.6s154.1–181.9s
Multithreaded MSBuild5159.0s160.7s144.2–168.3s

Local average improved by 8.1 seconds (4.8%) and median by 5.9 seconds (3.6%). The ranges overlap, so this is directional rather than statistically conclusive.

CI benchmark

Azure Pipelines build 1566758 succeeded in every configuration. The baseline is the average build-step duration from the four most recent successful fork PR builds (1566681, 1564881, 1564777, and 1564593), which use the same cache-disabled fallback path and are therefore more comparable than trusted-branch cache builds.

Build stepMultithreadedFork PR baselineChange
Windows Debug666.1s715.0s-6.8%
Windows Release685.5s692.4s-1.0%
Linux Debug367.1s367.1s0.0%
Linux Release352.1s369.5s-4.7%
macOS Debug663.0s702.8s-5.7%
macOS Release513.3s850.6s-39.7%

The two Windows configurations improved from 703.7s to 675.8s combined (-4.0%), closely matching the 4.8% local average improvement. Linux is neutral-to-modestly faster. macOS is highly variable—the baseline samples range from 533.7s to 1,015.6s for Debug and 723.9s to 1,021.9s for Release—so the apparent Release gain should not be treated as a reliable estimate.

MSBuildCache compatibility finding

The first experiment, build 1566674, failed because the cache-disabled Windows fallback still imported Microsoft.MSBuildCache.SharedCompilation. Its unannotated ResolveFileAccesses task was routed to a sidecar TaskHost under -mt. MSBuild then corrupted the returned FileAccessData structs during TaskHost packet deserialization through interface boxing and crashed in FileAccessManager.ReportFileAccess when replaying a null path.

The ProjectCachePlugin itself was inactive, so this was not a cache lookup or materialization race. The engine defect is tracked by dotnet/msbuild#14824.

This PR therefore keeps cache graph and cache-specific sign/pack operations process-based. Ordinary Windows fallback builds use -mt without importing cache support packages; Linux and macOS ordinary builds also use -mt.

Conclusion

Multithreaded MSBuild provides a modest end-to-end improvement on Windows: 4.8% locally and 4.0% in comparable PR CI, with no corrected-run failures. Linux results are consistent with a smaller improvement, while current macOS variance is too high for a precise estimate. Cache population and multithreaded execution should remain separate experiments until the TaskHost file-access serialization defect is fixed and their combined topology can be evaluated independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI balanced review requested due to automatic review settings August 25, 2026 11:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables multithreaded MSBuild for local Windows builds and public CI builds while leaving official builds unchanged.

Changes:

  • Defaults local PowerShell builds to multithreaded mode.
  • Enables multithreading across public Windows, Linux, and macOS CI paths.
  • Identified missing equivalent default for local Unix builds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
eng/build.ps1Configures the local PowerShell default.
azure-pipelines.ymlEnables multithreading in public CI build paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadeng/build.ps1
Comment on lines +86 to +87
if (-not $PSBoundParameters.ContainsKey("msbuildMultiThreaded")) {
$PSBoundParameters["msbuildMultiThreaded"] = -not $ci
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Build Failure Analysis

Summary — Enabling MSBuild's new -msbuildMultiThreaded (-mt) mode in this PR triggers a NullReferenceException inside the ResolveFileAccesses MSBuild task shipped by the Microsoft.MSBuildCache.SharedCompilation package, failing every Windows build leg (Release and Debug); the Linux/macOS legs (which don't hit this code path) compiled cleanly.

Root cause: -mt is incompatible with Microsoft.MSBuildCache.SharedCompilation's ResolveFileAccesses task

This PR adds -msbuildMultiThreaded/-mt to the CI invocations in azure-pipelines.yml and threads the corresponding parameter through eng/build.ps1. On both Windows Release and Windows Debug legs, MSBuild fails 13 projects (e.g. Microsoft.Testing.Platform, TestFramework.SourceGeneration, TestFramework, MSTest.Analyzers, MSTest.SourceGeneration, MSTest.Sdk) with the identical stack:

MSB4018: The "ResolveFileAccesses" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Build.FileAccesses.FileAccessManager.ReportFileAccess(FileAccessData fileAccessData, Int32 nodeId)
at Microsoft.Build.BackEnd.TaskHostTask.HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
at Microsoft.Build.BackEnd.TaskHostTask.HandlePacket(INodePacket packet, Boolean& taskFinished)
at Microsoft.Build.BackEnd.TaskHostTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9 in the ResolveCoreCompileFileAccesses target of the restored .packages\microsoft.msbuildcache.sharedcompilation\0.1.328-preview package. This repo already uses that MSBuildCache package for shared/out-of-proc compilation, which relies on MSBuild's TaskHostTask/FileAccessManager file-access-reporting plumbing (used for build-output caching). Turning on -mt changes MSBuild's node/threading model for concurrent task execution and file-access reporting; FileAccessManager.ReportFileAccess null-refs when it receives a completion callback for a node id it apparently doesn't have registered under multi-threaded execution — an incompatibility between this MSBuildCache version's file-access hook and -mt mode, not a defect in TestFx's own source.

Evidence that isolates -mt as the trigger:

  • Only the Windows legs that pass -msbuildMultiThreaded:$true/-mt (Windows Release, Windows Debug) fail; the Windows application-model acceptance leg, both Linux legs, and both macOS legs built cleanly.
  • Every failing project fails at the exact same target/task/line (ResolveCoreCompileFileAccessesResolveFileAccesses, SharedCompilation.targets:9) — one root cause fanning out across 13 projects, not 13 independent bugs.
  • No C#/analyzer compiler errors were reported anywhere in either failing leg — the actual compile never runs; the crash happens in the file-access-tracking wrapper around the compile task itself.

Affected projects (13 total, identical stack; representative subset)

  • src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
  • src/Platform/Microsoft.Testing.Platform.ServerMode.Client.Sources/...csproj
  • src/TestFramework/TestFramework.SourceGeneration/TestFramework.SourceGeneration.csproj
  • src/TestFramework/TestFramework/TestFramework.csproj (Debug leg only)
  • src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
  • src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj
  • src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj
  • src/Package/MSTest.Sdk/MSTest.Sdk.csproj
  • test/IntegrationTests/TestAssets/SampleProjectForAssemblyResolution/...csproj
  • samples/CtrfPlayground/XunitMtp/XunitMtp.csproj

Suggested fix

This is a build-infrastructure/tooling incompatibility, not a TestFx source-code bug, so it falls outside this workflow's automated fix-commit scope (limited to src//test/; eng/build.ps1 and azure-pipelines.yml are both excluded, and the fix is not a mechanical rename provable from a compiler error anyway). Two viable directions for a maintainer:

  1. Don't enable -mt on legs where Microsoft.MSBuildCache.SharedCompilation is active until that package (currently pinned at 0.1.328-preview) ships a fix for -mt compatibility — i.e. drop the newly-added -msbuildMultiThreaded lines for the Windows Release/Debug stages in azure-pipelines.yml, or gate them behind whether MSBuildCache is enabled for that leg.
  2. If -mt is required for this PR's goal, file/check for an upstream issue against Microsoft.MSBuildCache for -mt (multi-threaded node) compatibility with its ResolveFileAccesses/FileAccessManager file-access-tracking hook, and bump the package once fixed.

Since the crash originates inside a third-party MSBuild extension package rather than TestFx source, no inline code suggestion is offered — reverting or gating the newly-added -mt flags on the affected legs is the pragmatic short-term mitigation.


Build overview (Windows Release leg)
Build: FAILED
Duration: 156.2s
MSBuild: 18.10.0-1.26379.9+c88db8eb0
Projects: 74 Errors: 13 Warnings: 1
All MSBuild errors (13, identical across Windows Release + Windows Debug legs)
CodeTaskTargetRoot message
MSB4018ResolveFileAccessesResolveCoreCompileFileAccessesNullReferenceException in FileAccessManager.ReportFileAccess, thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9

(13 occurrences across each failing leg, one per failed project, all sharing this identical stack trace.)


🤖 Generated by the Build Failure Analysis workflow using (a href="(dev.azure.com/redacted) · commit ca552a2

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · auto · 92.4 AIC · ⌖ 1.74 AIC · ⊞ 13.3K · [◷]( · )

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 25, 2026 12:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JanProvaznik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Enable multithreaded MSBuild for local and PR builds by JanProvaznik · Pull Request #10726 · microsoft/testfx · GitHub
Skip to content

Enable multithreaded MSBuild for local and PR builds - #10726

Draft
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded
Draft

Enable multithreaded MSBuild for local and PR builds#10726
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded

Conversation

@JanProvaznik

@JanProvaznikJan Provazník (JanProvaznik) commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • enable MSBuild's experimental multithreaded mode by default for local builds
  • enable multithreaded MSBuild explicitly in ordinary public/PR Azure Pipelines builds on Windows, Linux, and macOS
  • keep MSBuildCache graph/cache follow-up builds process-based
  • keep the official build pipeline unchanged

Local benchmark

Measured five clean-output restore+build runs per mode after warming the SDK, workload, and NuGet caches on an 8-core/16-logical-processor Windows machine.

ModeRunsAverageMedianRange
Existing process-based MSBuild5167.1s166.6s154.1–181.9s
Multithreaded MSBuild5159.0s160.7s144.2–168.3s

Local average improved by 8.1 seconds (4.8%) and median by 5.9 seconds (3.6%). The ranges overlap, so this is directional rather than statistically conclusive.

CI benchmark

Azure Pipelines build 1566758 succeeded in every configuration. The baseline is the average build-step duration from the four most recent successful fork PR builds (1566681, 1564881, 1564777, and 1564593), which use the same cache-disabled fallback path and are therefore more comparable than trusted-branch cache builds.

Build stepMultithreadedFork PR baselineChange
Windows Debug666.1s715.0s-6.8%
Windows Release685.5s692.4s-1.0%
Linux Debug367.1s367.1s0.0%
Linux Release352.1s369.5s-4.7%
macOS Debug663.0s702.8s-5.7%
macOS Release513.3s850.6s-39.7%

The two Windows configurations improved from 703.7s to 675.8s combined (-4.0%), closely matching the 4.8% local average improvement. Linux is neutral-to-modestly faster. macOS is highly variable—the baseline samples range from 533.7s to 1,015.6s for Debug and 723.9s to 1,021.9s for Release—so the apparent Release gain should not be treated as a reliable estimate.

MSBuildCache compatibility finding

The first experiment, build 1566674, failed because the cache-disabled Windows fallback still imported Microsoft.MSBuildCache.SharedCompilation. Its unannotated ResolveFileAccesses task was routed to a sidecar TaskHost under -mt. MSBuild then corrupted the returned FileAccessData structs during TaskHost packet deserialization through interface boxing and crashed in FileAccessManager.ReportFileAccess when replaying a null path.

The ProjectCachePlugin itself was inactive, so this was not a cache lookup or materialization race. The engine defect is tracked by dotnet/msbuild#14824.

This PR therefore keeps cache graph and cache-specific sign/pack operations process-based. Ordinary Windows fallback builds use -mt without importing cache support packages; Linux and macOS ordinary builds also use -mt.

Conclusion

Multithreaded MSBuild provides a modest end-to-end improvement on Windows: 4.8% locally and 4.0% in comparable PR CI, with no corrected-run failures. Linux results are consistent with a smaller improvement, while current macOS variance is too high for a precise estimate. Cache population and multithreaded execution should remain separate experiments until the TaskHost file-access serialization defect is fixed and their combined topology can be evaluated independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI balanced review requested due to automatic review settings August 25, 2026 11:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables multithreaded MSBuild for local Windows builds and public CI builds while leaving official builds unchanged.

Changes:

  • Defaults local PowerShell builds to multithreaded mode.
  • Enables multithreading across public Windows, Linux, and macOS CI paths.
  • Identified missing equivalent default for local Unix builds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
eng/build.ps1Configures the local PowerShell default.
azure-pipelines.ymlEnables multithreading in public CI build paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadeng/build.ps1
Comment on lines +86 to +87
if (-not $PSBoundParameters.ContainsKey("msbuildMultiThreaded")) {
$PSBoundParameters["msbuildMultiThreaded"] = -not $ci
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Build Failure Analysis

Summary — Enabling MSBuild's new -msbuildMultiThreaded (-mt) mode in this PR triggers a NullReferenceException inside the ResolveFileAccesses MSBuild task shipped by the Microsoft.MSBuildCache.SharedCompilation package, failing every Windows build leg (Release and Debug); the Linux/macOS legs (which don't hit this code path) compiled cleanly.

Root cause: -mt is incompatible with Microsoft.MSBuildCache.SharedCompilation's ResolveFileAccesses task

This PR adds -msbuildMultiThreaded/-mt to the CI invocations in azure-pipelines.yml and threads the corresponding parameter through eng/build.ps1. On both Windows Release and Windows Debug legs, MSBuild fails 13 projects (e.g. Microsoft.Testing.Platform, TestFramework.SourceGeneration, TestFramework, MSTest.Analyzers, MSTest.SourceGeneration, MSTest.Sdk) with the identical stack:

MSB4018: The "ResolveFileAccesses" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Build.FileAccesses.FileAccessManager.ReportFileAccess(FileAccessData fileAccessData, Int32 nodeId)
at Microsoft.Build.BackEnd.TaskHostTask.HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
at Microsoft.Build.BackEnd.TaskHostTask.HandlePacket(INodePacket packet, Boolean& taskFinished)
at Microsoft.Build.BackEnd.TaskHostTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9 in the ResolveCoreCompileFileAccesses target of the restored .packages\microsoft.msbuildcache.sharedcompilation\0.1.328-preview package. This repo already uses that MSBuildCache package for shared/out-of-proc compilation, which relies on MSBuild's TaskHostTask/FileAccessManager file-access-reporting plumbing (used for build-output caching). Turning on -mt changes MSBuild's node/threading model for concurrent task execution and file-access reporting; FileAccessManager.ReportFileAccess null-refs when it receives a completion callback for a node id it apparently doesn't have registered under multi-threaded execution — an incompatibility between this MSBuildCache version's file-access hook and -mt mode, not a defect in TestFx's own source.

Evidence that isolates -mt as the trigger:

  • Only the Windows legs that pass -msbuildMultiThreaded:$true/-mt (Windows Release, Windows Debug) fail; the Windows application-model acceptance leg, both Linux legs, and both macOS legs built cleanly.
  • Every failing project fails at the exact same target/task/line (ResolveCoreCompileFileAccessesResolveFileAccesses, SharedCompilation.targets:9) — one root cause fanning out across 13 projects, not 13 independent bugs.
  • No C#/analyzer compiler errors were reported anywhere in either failing leg — the actual compile never runs; the crash happens in the file-access-tracking wrapper around the compile task itself.

Affected projects (13 total, identical stack; representative subset)

  • src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
  • src/Platform/Microsoft.Testing.Platform.ServerMode.Client.Sources/...csproj
  • src/TestFramework/TestFramework.SourceGeneration/TestFramework.SourceGeneration.csproj
  • src/TestFramework/TestFramework/TestFramework.csproj (Debug leg only)
  • src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
  • src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj
  • src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj
  • src/Package/MSTest.Sdk/MSTest.Sdk.csproj
  • test/IntegrationTests/TestAssets/SampleProjectForAssemblyResolution/...csproj
  • samples/CtrfPlayground/XunitMtp/XunitMtp.csproj

Suggested fix

This is a build-infrastructure/tooling incompatibility, not a TestFx source-code bug, so it falls outside this workflow's automated fix-commit scope (limited to src//test/; eng/build.ps1 and azure-pipelines.yml are both excluded, and the fix is not a mechanical rename provable from a compiler error anyway). Two viable directions for a maintainer:

  1. Don't enable -mt on legs where Microsoft.MSBuildCache.SharedCompilation is active until that package (currently pinned at 0.1.328-preview) ships a fix for -mt compatibility — i.e. drop the newly-added -msbuildMultiThreaded lines for the Windows Release/Debug stages in azure-pipelines.yml, or gate them behind whether MSBuildCache is enabled for that leg.
  2. If -mt is required for this PR's goal, file/check for an upstream issue against Microsoft.MSBuildCache for -mt (multi-threaded node) compatibility with its ResolveFileAccesses/FileAccessManager file-access-tracking hook, and bump the package once fixed.

Since the crash originates inside a third-party MSBuild extension package rather than TestFx source, no inline code suggestion is offered — reverting or gating the newly-added -mt flags on the affected legs is the pragmatic short-term mitigation.


Build overview (Windows Release leg)
Build: FAILED
Duration: 156.2s
MSBuild: 18.10.0-1.26379.9+c88db8eb0
Projects: 74 Errors: 13 Warnings: 1
All MSBuild errors (13, identical across Windows Release + Windows Debug legs)
CodeTaskTargetRoot message
MSB4018ResolveFileAccessesResolveCoreCompileFileAccessesNullReferenceException in FileAccessManager.ReportFileAccess, thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9

(13 occurrences across each failing leg, one per failed project, all sharing this identical stack trace.)


🤖 Generated by the Build Failure Analysis workflow using (a href="(dev.azure.com/redacted) · commit ca552a2

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · auto · 92.4 AIC · ⌖ 1.74 AIC · ⊞ 13.3K · [◷]( · )

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 25, 2026 12:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JanProvaznik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Enable multithreaded MSBuild for local and PR builds by JanProvaznik · Pull Request #10726 · microsoft/testfx · GitHub
Skip to content

Enable multithreaded MSBuild for local and PR builds - #10726

Draft
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded
Draft

Enable multithreaded MSBuild for local and PR builds#10726
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded

Conversation

@JanProvaznik

@JanProvaznikJan Provazník (JanProvaznik) commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • enable MSBuild's experimental multithreaded mode by default for local builds
  • enable multithreaded MSBuild explicitly in ordinary public/PR Azure Pipelines builds on Windows, Linux, and macOS
  • keep MSBuildCache graph/cache follow-up builds process-based
  • keep the official build pipeline unchanged

Local benchmark

Measured five clean-output restore+build runs per mode after warming the SDK, workload, and NuGet caches on an 8-core/16-logical-processor Windows machine.

ModeRunsAverageMedianRange
Existing process-based MSBuild5167.1s166.6s154.1–181.9s
Multithreaded MSBuild5159.0s160.7s144.2–168.3s

Local average improved by 8.1 seconds (4.8%) and median by 5.9 seconds (3.6%). The ranges overlap, so this is directional rather than statistically conclusive.

CI benchmark

Azure Pipelines build 1566758 succeeded in every configuration. The baseline is the average build-step duration from the four most recent successful fork PR builds (1566681, 1564881, 1564777, and 1564593), which use the same cache-disabled fallback path and are therefore more comparable than trusted-branch cache builds.

Build stepMultithreadedFork PR baselineChange
Windows Debug666.1s715.0s-6.8%
Windows Release685.5s692.4s-1.0%
Linux Debug367.1s367.1s0.0%
Linux Release352.1s369.5s-4.7%
macOS Debug663.0s702.8s-5.7%
macOS Release513.3s850.6s-39.7%

The two Windows configurations improved from 703.7s to 675.8s combined (-4.0%), closely matching the 4.8% local average improvement. Linux is neutral-to-modestly faster. macOS is highly variable—the baseline samples range from 533.7s to 1,015.6s for Debug and 723.9s to 1,021.9s for Release—so the apparent Release gain should not be treated as a reliable estimate.

MSBuildCache compatibility finding

The first experiment, build 1566674, failed because the cache-disabled Windows fallback still imported Microsoft.MSBuildCache.SharedCompilation. Its unannotated ResolveFileAccesses task was routed to a sidecar TaskHost under -mt. MSBuild then corrupted the returned FileAccessData structs during TaskHost packet deserialization through interface boxing and crashed in FileAccessManager.ReportFileAccess when replaying a null path.

The ProjectCachePlugin itself was inactive, so this was not a cache lookup or materialization race. The engine defect is tracked by dotnet/msbuild#14824.

This PR therefore keeps cache graph and cache-specific sign/pack operations process-based. Ordinary Windows fallback builds use -mt without importing cache support packages; Linux and macOS ordinary builds also use -mt.

Conclusion

Multithreaded MSBuild provides a modest end-to-end improvement on Windows: 4.8% locally and 4.0% in comparable PR CI, with no corrected-run failures. Linux results are consistent with a smaller improvement, while current macOS variance is too high for a precise estimate. Cache population and multithreaded execution should remain separate experiments until the TaskHost file-access serialization defect is fixed and their combined topology can be evaluated independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI balanced review requested due to automatic review settings August 25, 2026 11:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables multithreaded MSBuild for local Windows builds and public CI builds while leaving official builds unchanged.

Changes:

  • Defaults local PowerShell builds to multithreaded mode.
  • Enables multithreading across public Windows, Linux, and macOS CI paths.
  • Identified missing equivalent default for local Unix builds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
eng/build.ps1Configures the local PowerShell default.
azure-pipelines.ymlEnables multithreading in public CI build paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadeng/build.ps1
Comment on lines +86 to +87
if (-not $PSBoundParameters.ContainsKey("msbuildMultiThreaded")) {
$PSBoundParameters["msbuildMultiThreaded"] = -not $ci
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Build Failure Analysis

Summary — Enabling MSBuild's new -msbuildMultiThreaded (-mt) mode in this PR triggers a NullReferenceException inside the ResolveFileAccesses MSBuild task shipped by the Microsoft.MSBuildCache.SharedCompilation package, failing every Windows build leg (Release and Debug); the Linux/macOS legs (which don't hit this code path) compiled cleanly.

Root cause: -mt is incompatible with Microsoft.MSBuildCache.SharedCompilation's ResolveFileAccesses task

This PR adds -msbuildMultiThreaded/-mt to the CI invocations in azure-pipelines.yml and threads the corresponding parameter through eng/build.ps1. On both Windows Release and Windows Debug legs, MSBuild fails 13 projects (e.g. Microsoft.Testing.Platform, TestFramework.SourceGeneration, TestFramework, MSTest.Analyzers, MSTest.SourceGeneration, MSTest.Sdk) with the identical stack:

MSB4018: The "ResolveFileAccesses" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Build.FileAccesses.FileAccessManager.ReportFileAccess(FileAccessData fileAccessData, Int32 nodeId)
at Microsoft.Build.BackEnd.TaskHostTask.HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
at Microsoft.Build.BackEnd.TaskHostTask.HandlePacket(INodePacket packet, Boolean& taskFinished)
at Microsoft.Build.BackEnd.TaskHostTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9 in the ResolveCoreCompileFileAccesses target of the restored .packages\microsoft.msbuildcache.sharedcompilation\0.1.328-preview package. This repo already uses that MSBuildCache package for shared/out-of-proc compilation, which relies on MSBuild's TaskHostTask/FileAccessManager file-access-reporting plumbing (used for build-output caching). Turning on -mt changes MSBuild's node/threading model for concurrent task execution and file-access reporting; FileAccessManager.ReportFileAccess null-refs when it receives a completion callback for a node id it apparently doesn't have registered under multi-threaded execution — an incompatibility between this MSBuildCache version's file-access hook and -mt mode, not a defect in TestFx's own source.

Evidence that isolates -mt as the trigger:

  • Only the Windows legs that pass -msbuildMultiThreaded:$true/-mt (Windows Release, Windows Debug) fail; the Windows application-model acceptance leg, both Linux legs, and both macOS legs built cleanly.
  • Every failing project fails at the exact same target/task/line (ResolveCoreCompileFileAccessesResolveFileAccesses, SharedCompilation.targets:9) — one root cause fanning out across 13 projects, not 13 independent bugs.
  • No C#/analyzer compiler errors were reported anywhere in either failing leg — the actual compile never runs; the crash happens in the file-access-tracking wrapper around the compile task itself.

Affected projects (13 total, identical stack; representative subset)

  • src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
  • src/Platform/Microsoft.Testing.Platform.ServerMode.Client.Sources/...csproj
  • src/TestFramework/TestFramework.SourceGeneration/TestFramework.SourceGeneration.csproj
  • src/TestFramework/TestFramework/TestFramework.csproj (Debug leg only)
  • src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
  • src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj
  • src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj
  • src/Package/MSTest.Sdk/MSTest.Sdk.csproj
  • test/IntegrationTests/TestAssets/SampleProjectForAssemblyResolution/...csproj
  • samples/CtrfPlayground/XunitMtp/XunitMtp.csproj

Suggested fix

This is a build-infrastructure/tooling incompatibility, not a TestFx source-code bug, so it falls outside this workflow's automated fix-commit scope (limited to src//test/; eng/build.ps1 and azure-pipelines.yml are both excluded, and the fix is not a mechanical rename provable from a compiler error anyway). Two viable directions for a maintainer:

  1. Don't enable -mt on legs where Microsoft.MSBuildCache.SharedCompilation is active until that package (currently pinned at 0.1.328-preview) ships a fix for -mt compatibility — i.e. drop the newly-added -msbuildMultiThreaded lines for the Windows Release/Debug stages in azure-pipelines.yml, or gate them behind whether MSBuildCache is enabled for that leg.
  2. If -mt is required for this PR's goal, file/check for an upstream issue against Microsoft.MSBuildCache for -mt (multi-threaded node) compatibility with its ResolveFileAccesses/FileAccessManager file-access-tracking hook, and bump the package once fixed.

Since the crash originates inside a third-party MSBuild extension package rather than TestFx source, no inline code suggestion is offered — reverting or gating the newly-added -mt flags on the affected legs is the pragmatic short-term mitigation.


Build overview (Windows Release leg)
Build: FAILED
Duration: 156.2s
MSBuild: 18.10.0-1.26379.9+c88db8eb0
Projects: 74 Errors: 13 Warnings: 1
All MSBuild errors (13, identical across Windows Release + Windows Debug legs)
CodeTaskTargetRoot message
MSB4018ResolveFileAccessesResolveCoreCompileFileAccessesNullReferenceException in FileAccessManager.ReportFileAccess, thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9

(13 occurrences across each failing leg, one per failed project, all sharing this identical stack trace.)


🤖 Generated by the Build Failure Analysis workflow using (a href="(dev.azure.com/redacted) · commit ca552a2

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · auto · 92.4 AIC · ⌖ 1.74 AIC · ⊞ 13.3K · [◷]( · )

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 25, 2026 12:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JanProvaznik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Enable multithreaded MSBuild for local and PR builds by JanProvaznik · Pull Request #10726 · microsoft/testfx · GitHub
Skip to content

Enable multithreaded MSBuild for local and PR builds - #10726

Draft
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded
Draft

Enable multithreaded MSBuild for local and PR builds#10726
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded

Conversation

@JanProvaznik

@JanProvaznikJan Provazník (JanProvaznik) commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • enable MSBuild's experimental multithreaded mode by default for local builds
  • enable multithreaded MSBuild explicitly in ordinary public/PR Azure Pipelines builds on Windows, Linux, and macOS
  • keep MSBuildCache graph/cache follow-up builds process-based
  • keep the official build pipeline unchanged

Local benchmark

Measured five clean-output restore+build runs per mode after warming the SDK, workload, and NuGet caches on an 8-core/16-logical-processor Windows machine.

ModeRunsAverageMedianRange
Existing process-based MSBuild5167.1s166.6s154.1–181.9s
Multithreaded MSBuild5159.0s160.7s144.2–168.3s

Local average improved by 8.1 seconds (4.8%) and median by 5.9 seconds (3.6%). The ranges overlap, so this is directional rather than statistically conclusive.

CI benchmark

Azure Pipelines build 1566758 succeeded in every configuration. The baseline is the average build-step duration from the four most recent successful fork PR builds (1566681, 1564881, 1564777, and 1564593), which use the same cache-disabled fallback path and are therefore more comparable than trusted-branch cache builds.

Build stepMultithreadedFork PR baselineChange
Windows Debug666.1s715.0s-6.8%
Windows Release685.5s692.4s-1.0%
Linux Debug367.1s367.1s0.0%
Linux Release352.1s369.5s-4.7%
macOS Debug663.0s702.8s-5.7%
macOS Release513.3s850.6s-39.7%

The two Windows configurations improved from 703.7s to 675.8s combined (-4.0%), closely matching the 4.8% local average improvement. Linux is neutral-to-modestly faster. macOS is highly variable—the baseline samples range from 533.7s to 1,015.6s for Debug and 723.9s to 1,021.9s for Release—so the apparent Release gain should not be treated as a reliable estimate.

MSBuildCache compatibility finding

The first experiment, build 1566674, failed because the cache-disabled Windows fallback still imported Microsoft.MSBuildCache.SharedCompilation. Its unannotated ResolveFileAccesses task was routed to a sidecar TaskHost under -mt. MSBuild then corrupted the returned FileAccessData structs during TaskHost packet deserialization through interface boxing and crashed in FileAccessManager.ReportFileAccess when replaying a null path.

The ProjectCachePlugin itself was inactive, so this was not a cache lookup or materialization race. The engine defect is tracked by dotnet/msbuild#14824.

This PR therefore keeps cache graph and cache-specific sign/pack operations process-based. Ordinary Windows fallback builds use -mt without importing cache support packages; Linux and macOS ordinary builds also use -mt.

Conclusion

Multithreaded MSBuild provides a modest end-to-end improvement on Windows: 4.8% locally and 4.0% in comparable PR CI, with no corrected-run failures. Linux results are consistent with a smaller improvement, while current macOS variance is too high for a precise estimate. Cache population and multithreaded execution should remain separate experiments until the TaskHost file-access serialization defect is fixed and their combined topology can be evaluated independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI balanced review requested due to automatic review settings August 25, 2026 11:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables multithreaded MSBuild for local Windows builds and public CI builds while leaving official builds unchanged.

Changes:

  • Defaults local PowerShell builds to multithreaded mode.
  • Enables multithreading across public Windows, Linux, and macOS CI paths.
  • Identified missing equivalent default for local Unix builds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
eng/build.ps1Configures the local PowerShell default.
azure-pipelines.ymlEnables multithreading in public CI build paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadeng/build.ps1
Comment on lines +86 to +87
if (-not $PSBoundParameters.ContainsKey("msbuildMultiThreaded")) {
$PSBoundParameters["msbuildMultiThreaded"] = -not $ci
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Build Failure Analysis

Summary — Enabling MSBuild's new -msbuildMultiThreaded (-mt) mode in this PR triggers a NullReferenceException inside the ResolveFileAccesses MSBuild task shipped by the Microsoft.MSBuildCache.SharedCompilation package, failing every Windows build leg (Release and Debug); the Linux/macOS legs (which don't hit this code path) compiled cleanly.

Root cause: -mt is incompatible with Microsoft.MSBuildCache.SharedCompilation's ResolveFileAccesses task

This PR adds -msbuildMultiThreaded/-mt to the CI invocations in azure-pipelines.yml and threads the corresponding parameter through eng/build.ps1. On both Windows Release and Windows Debug legs, MSBuild fails 13 projects (e.g. Microsoft.Testing.Platform, TestFramework.SourceGeneration, TestFramework, MSTest.Analyzers, MSTest.SourceGeneration, MSTest.Sdk) with the identical stack:

MSB4018: The "ResolveFileAccesses" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Build.FileAccesses.FileAccessManager.ReportFileAccess(FileAccessData fileAccessData, Int32 nodeId)
at Microsoft.Build.BackEnd.TaskHostTask.HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
at Microsoft.Build.BackEnd.TaskHostTask.HandlePacket(INodePacket packet, Boolean& taskFinished)
at Microsoft.Build.BackEnd.TaskHostTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9 in the ResolveCoreCompileFileAccesses target of the restored .packages\microsoft.msbuildcache.sharedcompilation\0.1.328-preview package. This repo already uses that MSBuildCache package for shared/out-of-proc compilation, which relies on MSBuild's TaskHostTask/FileAccessManager file-access-reporting plumbing (used for build-output caching). Turning on -mt changes MSBuild's node/threading model for concurrent task execution and file-access reporting; FileAccessManager.ReportFileAccess null-refs when it receives a completion callback for a node id it apparently doesn't have registered under multi-threaded execution — an incompatibility between this MSBuildCache version's file-access hook and -mt mode, not a defect in TestFx's own source.

Evidence that isolates -mt as the trigger:

  • Only the Windows legs that pass -msbuildMultiThreaded:$true/-mt (Windows Release, Windows Debug) fail; the Windows application-model acceptance leg, both Linux legs, and both macOS legs built cleanly.
  • Every failing project fails at the exact same target/task/line (ResolveCoreCompileFileAccessesResolveFileAccesses, SharedCompilation.targets:9) — one root cause fanning out across 13 projects, not 13 independent bugs.
  • No C#/analyzer compiler errors were reported anywhere in either failing leg — the actual compile never runs; the crash happens in the file-access-tracking wrapper around the compile task itself.

Affected projects (13 total, identical stack; representative subset)

  • src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
  • src/Platform/Microsoft.Testing.Platform.ServerMode.Client.Sources/...csproj
  • src/TestFramework/TestFramework.SourceGeneration/TestFramework.SourceGeneration.csproj
  • src/TestFramework/TestFramework/TestFramework.csproj (Debug leg only)
  • src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
  • src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj
  • src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj
  • src/Package/MSTest.Sdk/MSTest.Sdk.csproj
  • test/IntegrationTests/TestAssets/SampleProjectForAssemblyResolution/...csproj
  • samples/CtrfPlayground/XunitMtp/XunitMtp.csproj

Suggested fix

This is a build-infrastructure/tooling incompatibility, not a TestFx source-code bug, so it falls outside this workflow's automated fix-commit scope (limited to src//test/; eng/build.ps1 and azure-pipelines.yml are both excluded, and the fix is not a mechanical rename provable from a compiler error anyway). Two viable directions for a maintainer:

  1. Don't enable -mt on legs where Microsoft.MSBuildCache.SharedCompilation is active until that package (currently pinned at 0.1.328-preview) ships a fix for -mt compatibility — i.e. drop the newly-added -msbuildMultiThreaded lines for the Windows Release/Debug stages in azure-pipelines.yml, or gate them behind whether MSBuildCache is enabled for that leg.
  2. If -mt is required for this PR's goal, file/check for an upstream issue against Microsoft.MSBuildCache for -mt (multi-threaded node) compatibility with its ResolveFileAccesses/FileAccessManager file-access-tracking hook, and bump the package once fixed.

Since the crash originates inside a third-party MSBuild extension package rather than TestFx source, no inline code suggestion is offered — reverting or gating the newly-added -mt flags on the affected legs is the pragmatic short-term mitigation.


Build overview (Windows Release leg)
Build: FAILED
Duration: 156.2s
MSBuild: 18.10.0-1.26379.9+c88db8eb0
Projects: 74 Errors: 13 Warnings: 1
All MSBuild errors (13, identical across Windows Release + Windows Debug legs)
CodeTaskTargetRoot message
MSB4018ResolveFileAccessesResolveCoreCompileFileAccessesNullReferenceException in FileAccessManager.ReportFileAccess, thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9

(13 occurrences across each failing leg, one per failed project, all sharing this identical stack trace.)


🤖 Generated by the Build Failure Analysis workflow using (a href="(dev.azure.com/redacted) · commit ca552a2

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · auto · 92.4 AIC · ⌖ 1.74 AIC · ⊞ 13.3K · [◷]( · )

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 25, 2026 12:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JanProvaznik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Enable multithreaded MSBuild for local and PR builds by JanProvaznik · Pull Request #10726 · microsoft/testfx · GitHub
Skip to content

Enable multithreaded MSBuild for local and PR builds - #10726

Draft
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded
Draft

Enable multithreaded MSBuild for local and PR builds#10726
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded

Conversation

@JanProvaznik

@JanProvaznikJan Provazník (JanProvaznik) commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • enable MSBuild's experimental multithreaded mode by default for local builds
  • enable multithreaded MSBuild explicitly in ordinary public/PR Azure Pipelines builds on Windows, Linux, and macOS
  • keep MSBuildCache graph/cache follow-up builds process-based
  • keep the official build pipeline unchanged

Local benchmark

Measured five clean-output restore+build runs per mode after warming the SDK, workload, and NuGet caches on an 8-core/16-logical-processor Windows machine.

ModeRunsAverageMedianRange
Existing process-based MSBuild5167.1s166.6s154.1–181.9s
Multithreaded MSBuild5159.0s160.7s144.2–168.3s

Local average improved by 8.1 seconds (4.8%) and median by 5.9 seconds (3.6%). The ranges overlap, so this is directional rather than statistically conclusive.

CI benchmark

Azure Pipelines build 1566758 succeeded in every configuration. The baseline is the average build-step duration from the four most recent successful fork PR builds (1566681, 1564881, 1564777, and 1564593), which use the same cache-disabled fallback path and are therefore more comparable than trusted-branch cache builds.

Build stepMultithreadedFork PR baselineChange
Windows Debug666.1s715.0s-6.8%
Windows Release685.5s692.4s-1.0%
Linux Debug367.1s367.1s0.0%
Linux Release352.1s369.5s-4.7%
macOS Debug663.0s702.8s-5.7%
macOS Release513.3s850.6s-39.7%

The two Windows configurations improved from 703.7s to 675.8s combined (-4.0%), closely matching the 4.8% local average improvement. Linux is neutral-to-modestly faster. macOS is highly variable—the baseline samples range from 533.7s to 1,015.6s for Debug and 723.9s to 1,021.9s for Release—so the apparent Release gain should not be treated as a reliable estimate.

MSBuildCache compatibility finding

The first experiment, build 1566674, failed because the cache-disabled Windows fallback still imported Microsoft.MSBuildCache.SharedCompilation. Its unannotated ResolveFileAccesses task was routed to a sidecar TaskHost under -mt. MSBuild then corrupted the returned FileAccessData structs during TaskHost packet deserialization through interface boxing and crashed in FileAccessManager.ReportFileAccess when replaying a null path.

The ProjectCachePlugin itself was inactive, so this was not a cache lookup or materialization race. The engine defect is tracked by dotnet/msbuild#14824.

This PR therefore keeps cache graph and cache-specific sign/pack operations process-based. Ordinary Windows fallback builds use -mt without importing cache support packages; Linux and macOS ordinary builds also use -mt.

Conclusion

Multithreaded MSBuild provides a modest end-to-end improvement on Windows: 4.8% locally and 4.0% in comparable PR CI, with no corrected-run failures. Linux results are consistent with a smaller improvement, while current macOS variance is too high for a precise estimate. Cache population and multithreaded execution should remain separate experiments until the TaskHost file-access serialization defect is fixed and their combined topology can be evaluated independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI balanced review requested due to automatic review settings August 25, 2026 11:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables multithreaded MSBuild for local Windows builds and public CI builds while leaving official builds unchanged.

Changes:

  • Defaults local PowerShell builds to multithreaded mode.
  • Enables multithreading across public Windows, Linux, and macOS CI paths.
  • Identified missing equivalent default for local Unix builds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
eng/build.ps1Configures the local PowerShell default.
azure-pipelines.ymlEnables multithreading in public CI build paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadeng/build.ps1
Comment on lines +86 to +87
if (-not $PSBoundParameters.ContainsKey("msbuildMultiThreaded")) {
$PSBoundParameters["msbuildMultiThreaded"] = -not $ci
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Build Failure Analysis

Summary — Enabling MSBuild's new -msbuildMultiThreaded (-mt) mode in this PR triggers a NullReferenceException inside the ResolveFileAccesses MSBuild task shipped by the Microsoft.MSBuildCache.SharedCompilation package, failing every Windows build leg (Release and Debug); the Linux/macOS legs (which don't hit this code path) compiled cleanly.

Root cause: -mt is incompatible with Microsoft.MSBuildCache.SharedCompilation's ResolveFileAccesses task

This PR adds -msbuildMultiThreaded/-mt to the CI invocations in azure-pipelines.yml and threads the corresponding parameter through eng/build.ps1. On both Windows Release and Windows Debug legs, MSBuild fails 13 projects (e.g. Microsoft.Testing.Platform, TestFramework.SourceGeneration, TestFramework, MSTest.Analyzers, MSTest.SourceGeneration, MSTest.Sdk) with the identical stack:

MSB4018: The "ResolveFileAccesses" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Build.FileAccesses.FileAccessManager.ReportFileAccess(FileAccessData fileAccessData, Int32 nodeId)
at Microsoft.Build.BackEnd.TaskHostTask.HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
at Microsoft.Build.BackEnd.TaskHostTask.HandlePacket(INodePacket packet, Boolean& taskFinished)
at Microsoft.Build.BackEnd.TaskHostTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9 in the ResolveCoreCompileFileAccesses target of the restored .packages\microsoft.msbuildcache.sharedcompilation\0.1.328-preview package. This repo already uses that MSBuildCache package for shared/out-of-proc compilation, which relies on MSBuild's TaskHostTask/FileAccessManager file-access-reporting plumbing (used for build-output caching). Turning on -mt changes MSBuild's node/threading model for concurrent task execution and file-access reporting; FileAccessManager.ReportFileAccess null-refs when it receives a completion callback for a node id it apparently doesn't have registered under multi-threaded execution — an incompatibility between this MSBuildCache version's file-access hook and -mt mode, not a defect in TestFx's own source.

Evidence that isolates -mt as the trigger:

  • Only the Windows legs that pass -msbuildMultiThreaded:$true/-mt (Windows Release, Windows Debug) fail; the Windows application-model acceptance leg, both Linux legs, and both macOS legs built cleanly.
  • Every failing project fails at the exact same target/task/line (ResolveCoreCompileFileAccessesResolveFileAccesses, SharedCompilation.targets:9) — one root cause fanning out across 13 projects, not 13 independent bugs.
  • No C#/analyzer compiler errors were reported anywhere in either failing leg — the actual compile never runs; the crash happens in the file-access-tracking wrapper around the compile task itself.

Affected projects (13 total, identical stack; representative subset)

  • src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
  • src/Platform/Microsoft.Testing.Platform.ServerMode.Client.Sources/...csproj
  • src/TestFramework/TestFramework.SourceGeneration/TestFramework.SourceGeneration.csproj
  • src/TestFramework/TestFramework/TestFramework.csproj (Debug leg only)
  • src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
  • src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj
  • src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj
  • src/Package/MSTest.Sdk/MSTest.Sdk.csproj
  • test/IntegrationTests/TestAssets/SampleProjectForAssemblyResolution/...csproj
  • samples/CtrfPlayground/XunitMtp/XunitMtp.csproj

Suggested fix

This is a build-infrastructure/tooling incompatibility, not a TestFx source-code bug, so it falls outside this workflow's automated fix-commit scope (limited to src//test/; eng/build.ps1 and azure-pipelines.yml are both excluded, and the fix is not a mechanical rename provable from a compiler error anyway). Two viable directions for a maintainer:

  1. Don't enable -mt on legs where Microsoft.MSBuildCache.SharedCompilation is active until that package (currently pinned at 0.1.328-preview) ships a fix for -mt compatibility — i.e. drop the newly-added -msbuildMultiThreaded lines for the Windows Release/Debug stages in azure-pipelines.yml, or gate them behind whether MSBuildCache is enabled for that leg.
  2. If -mt is required for this PR's goal, file/check for an upstream issue against Microsoft.MSBuildCache for -mt (multi-threaded node) compatibility with its ResolveFileAccesses/FileAccessManager file-access-tracking hook, and bump the package once fixed.

Since the crash originates inside a third-party MSBuild extension package rather than TestFx source, no inline code suggestion is offered — reverting or gating the newly-added -mt flags on the affected legs is the pragmatic short-term mitigation.


Build overview (Windows Release leg)
Build: FAILED
Duration: 156.2s
MSBuild: 18.10.0-1.26379.9+c88db8eb0
Projects: 74 Errors: 13 Warnings: 1
All MSBuild errors (13, identical across Windows Release + Windows Debug legs)
CodeTaskTargetRoot message
MSB4018ResolveFileAccessesResolveCoreCompileFileAccessesNullReferenceException in FileAccessManager.ReportFileAccess, thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9

(13 occurrences across each failing leg, one per failed project, all sharing this identical stack trace.)


🤖 Generated by the Build Failure Analysis workflow using (a href="(dev.azure.com/redacted) · commit ca552a2

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · auto · 92.4 AIC · ⌖ 1.74 AIC · ⊞ 13.3K · [◷]( · )

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 25, 2026 12:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JanProvaznik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Enable multithreaded MSBuild for local and PR builds by JanProvaznik · Pull Request #10726 · microsoft/testfx · GitHub
Skip to content

Enable multithreaded MSBuild for local and PR builds - #10726

Draft
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded
Draft

Enable multithreaded MSBuild for local and PR builds#10726
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded

Conversation

@JanProvaznik

@JanProvaznikJan Provazník (JanProvaznik) commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • enable MSBuild's experimental multithreaded mode by default for local builds
  • enable multithreaded MSBuild explicitly in ordinary public/PR Azure Pipelines builds on Windows, Linux, and macOS
  • keep MSBuildCache graph/cache follow-up builds process-based
  • keep the official build pipeline unchanged

Local benchmark

Measured five clean-output restore+build runs per mode after warming the SDK, workload, and NuGet caches on an 8-core/16-logical-processor Windows machine.

ModeRunsAverageMedianRange
Existing process-based MSBuild5167.1s166.6s154.1–181.9s
Multithreaded MSBuild5159.0s160.7s144.2–168.3s

Local average improved by 8.1 seconds (4.8%) and median by 5.9 seconds (3.6%). The ranges overlap, so this is directional rather than statistically conclusive.

CI benchmark

Azure Pipelines build 1566758 succeeded in every configuration. The baseline is the average build-step duration from the four most recent successful fork PR builds (1566681, 1564881, 1564777, and 1564593), which use the same cache-disabled fallback path and are therefore more comparable than trusted-branch cache builds.

Build stepMultithreadedFork PR baselineChange
Windows Debug666.1s715.0s-6.8%
Windows Release685.5s692.4s-1.0%
Linux Debug367.1s367.1s0.0%
Linux Release352.1s369.5s-4.7%
macOS Debug663.0s702.8s-5.7%
macOS Release513.3s850.6s-39.7%

The two Windows configurations improved from 703.7s to 675.8s combined (-4.0%), closely matching the 4.8% local average improvement. Linux is neutral-to-modestly faster. macOS is highly variable—the baseline samples range from 533.7s to 1,015.6s for Debug and 723.9s to 1,021.9s for Release—so the apparent Release gain should not be treated as a reliable estimate.

MSBuildCache compatibility finding

The first experiment, build 1566674, failed because the cache-disabled Windows fallback still imported Microsoft.MSBuildCache.SharedCompilation. Its unannotated ResolveFileAccesses task was routed to a sidecar TaskHost under -mt. MSBuild then corrupted the returned FileAccessData structs during TaskHost packet deserialization through interface boxing and crashed in FileAccessManager.ReportFileAccess when replaying a null path.

The ProjectCachePlugin itself was inactive, so this was not a cache lookup or materialization race. The engine defect is tracked by dotnet/msbuild#14824.

This PR therefore keeps cache graph and cache-specific sign/pack operations process-based. Ordinary Windows fallback builds use -mt without importing cache support packages; Linux and macOS ordinary builds also use -mt.

Conclusion

Multithreaded MSBuild provides a modest end-to-end improvement on Windows: 4.8% locally and 4.0% in comparable PR CI, with no corrected-run failures. Linux results are consistent with a smaller improvement, while current macOS variance is too high for a precise estimate. Cache population and multithreaded execution should remain separate experiments until the TaskHost file-access serialization defect is fixed and their combined topology can be evaluated independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI balanced review requested due to automatic review settings August 25, 2026 11:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables multithreaded MSBuild for local Windows builds and public CI builds while leaving official builds unchanged.

Changes:

  • Defaults local PowerShell builds to multithreaded mode.
  • Enables multithreading across public Windows, Linux, and macOS CI paths.
  • Identified missing equivalent default for local Unix builds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
eng/build.ps1Configures the local PowerShell default.
azure-pipelines.ymlEnables multithreading in public CI build paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadeng/build.ps1
Comment on lines +86 to +87
if (-not $PSBoundParameters.ContainsKey("msbuildMultiThreaded")) {
$PSBoundParameters["msbuildMultiThreaded"] = -not $ci
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Build Failure Analysis

Summary — Enabling MSBuild's new -msbuildMultiThreaded (-mt) mode in this PR triggers a NullReferenceException inside the ResolveFileAccesses MSBuild task shipped by the Microsoft.MSBuildCache.SharedCompilation package, failing every Windows build leg (Release and Debug); the Linux/macOS legs (which don't hit this code path) compiled cleanly.

Root cause: -mt is incompatible with Microsoft.MSBuildCache.SharedCompilation's ResolveFileAccesses task

This PR adds -msbuildMultiThreaded/-mt to the CI invocations in azure-pipelines.yml and threads the corresponding parameter through eng/build.ps1. On both Windows Release and Windows Debug legs, MSBuild fails 13 projects (e.g. Microsoft.Testing.Platform, TestFramework.SourceGeneration, TestFramework, MSTest.Analyzers, MSTest.SourceGeneration, MSTest.Sdk) with the identical stack:

MSB4018: The "ResolveFileAccesses" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Build.FileAccesses.FileAccessManager.ReportFileAccess(FileAccessData fileAccessData, Int32 nodeId)
at Microsoft.Build.BackEnd.TaskHostTask.HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
at Microsoft.Build.BackEnd.TaskHostTask.HandlePacket(INodePacket packet, Boolean& taskFinished)
at Microsoft.Build.BackEnd.TaskHostTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9 in the ResolveCoreCompileFileAccesses target of the restored .packages\microsoft.msbuildcache.sharedcompilation\0.1.328-preview package. This repo already uses that MSBuildCache package for shared/out-of-proc compilation, which relies on MSBuild's TaskHostTask/FileAccessManager file-access-reporting plumbing (used for build-output caching). Turning on -mt changes MSBuild's node/threading model for concurrent task execution and file-access reporting; FileAccessManager.ReportFileAccess null-refs when it receives a completion callback for a node id it apparently doesn't have registered under multi-threaded execution — an incompatibility between this MSBuildCache version's file-access hook and -mt mode, not a defect in TestFx's own source.

Evidence that isolates -mt as the trigger:

  • Only the Windows legs that pass -msbuildMultiThreaded:$true/-mt (Windows Release, Windows Debug) fail; the Windows application-model acceptance leg, both Linux legs, and both macOS legs built cleanly.
  • Every failing project fails at the exact same target/task/line (ResolveCoreCompileFileAccessesResolveFileAccesses, SharedCompilation.targets:9) — one root cause fanning out across 13 projects, not 13 independent bugs.
  • No C#/analyzer compiler errors were reported anywhere in either failing leg — the actual compile never runs; the crash happens in the file-access-tracking wrapper around the compile task itself.

Affected projects (13 total, identical stack; representative subset)

  • src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
  • src/Platform/Microsoft.Testing.Platform.ServerMode.Client.Sources/...csproj
  • src/TestFramework/TestFramework.SourceGeneration/TestFramework.SourceGeneration.csproj
  • src/TestFramework/TestFramework/TestFramework.csproj (Debug leg only)
  • src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
  • src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj
  • src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj
  • src/Package/MSTest.Sdk/MSTest.Sdk.csproj
  • test/IntegrationTests/TestAssets/SampleProjectForAssemblyResolution/...csproj
  • samples/CtrfPlayground/XunitMtp/XunitMtp.csproj

Suggested fix

This is a build-infrastructure/tooling incompatibility, not a TestFx source-code bug, so it falls outside this workflow's automated fix-commit scope (limited to src//test/; eng/build.ps1 and azure-pipelines.yml are both excluded, and the fix is not a mechanical rename provable from a compiler error anyway). Two viable directions for a maintainer:

  1. Don't enable -mt on legs where Microsoft.MSBuildCache.SharedCompilation is active until that package (currently pinned at 0.1.328-preview) ships a fix for -mt compatibility — i.e. drop the newly-added -msbuildMultiThreaded lines for the Windows Release/Debug stages in azure-pipelines.yml, or gate them behind whether MSBuildCache is enabled for that leg.
  2. If -mt is required for this PR's goal, file/check for an upstream issue against Microsoft.MSBuildCache for -mt (multi-threaded node) compatibility with its ResolveFileAccesses/FileAccessManager file-access-tracking hook, and bump the package once fixed.

Since the crash originates inside a third-party MSBuild extension package rather than TestFx source, no inline code suggestion is offered — reverting or gating the newly-added -mt flags on the affected legs is the pragmatic short-term mitigation.


Build overview (Windows Release leg)
Build: FAILED
Duration: 156.2s
MSBuild: 18.10.0-1.26379.9+c88db8eb0
Projects: 74 Errors: 13 Warnings: 1
All MSBuild errors (13, identical across Windows Release + Windows Debug legs)
CodeTaskTargetRoot message
MSB4018ResolveFileAccessesResolveCoreCompileFileAccessesNullReferenceException in FileAccessManager.ReportFileAccess, thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9

(13 occurrences across each failing leg, one per failed project, all sharing this identical stack trace.)


🤖 Generated by the Build Failure Analysis workflow using (a href="(dev.azure.com/redacted) · commit ca552a2

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · auto · 92.4 AIC · ⌖ 1.74 AIC · ⊞ 13.3K · [◷]( · )

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 25, 2026 12:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JanProvaznik
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Enable multithreaded MSBuild for local and PR builds by JanProvaznik · Pull Request #10726 · microsoft/testfx · GitHub
Skip to content

Enable multithreaded MSBuild for local and PR builds - #10726

Draft
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded
Draft

Enable multithreaded MSBuild for local and PR builds#10726
Jan Provazník (JanProvaznik) wants to merge 2 commits into
microsoft:mainfrom
JanProvaznik:perf/msbuild-multithreaded

Conversation

@JanProvaznik

@JanProvaznikJan Provazník (JanProvaznik) commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • enable MSBuild's experimental multithreaded mode by default for local builds
  • enable multithreaded MSBuild explicitly in ordinary public/PR Azure Pipelines builds on Windows, Linux, and macOS
  • keep MSBuildCache graph/cache follow-up builds process-based
  • keep the official build pipeline unchanged

Local benchmark

Measured five clean-output restore+build runs per mode after warming the SDK, workload, and NuGet caches on an 8-core/16-logical-processor Windows machine.

ModeRunsAverageMedianRange
Existing process-based MSBuild5167.1s166.6s154.1–181.9s
Multithreaded MSBuild5159.0s160.7s144.2–168.3s

Local average improved by 8.1 seconds (4.8%) and median by 5.9 seconds (3.6%). The ranges overlap, so this is directional rather than statistically conclusive.

CI benchmark

Azure Pipelines build 1566758 succeeded in every configuration. The baseline is the average build-step duration from the four most recent successful fork PR builds (1566681, 1564881, 1564777, and 1564593), which use the same cache-disabled fallback path and are therefore more comparable than trusted-branch cache builds.

Build stepMultithreadedFork PR baselineChange
Windows Debug666.1s715.0s-6.8%
Windows Release685.5s692.4s-1.0%
Linux Debug367.1s367.1s0.0%
Linux Release352.1s369.5s-4.7%
macOS Debug663.0s702.8s-5.7%
macOS Release513.3s850.6s-39.7%

The two Windows configurations improved from 703.7s to 675.8s combined (-4.0%), closely matching the 4.8% local average improvement. Linux is neutral-to-modestly faster. macOS is highly variable—the baseline samples range from 533.7s to 1,015.6s for Debug and 723.9s to 1,021.9s for Release—so the apparent Release gain should not be treated as a reliable estimate.

MSBuildCache compatibility finding

The first experiment, build 1566674, failed because the cache-disabled Windows fallback still imported Microsoft.MSBuildCache.SharedCompilation. Its unannotated ResolveFileAccesses task was routed to a sidecar TaskHost under -mt. MSBuild then corrupted the returned FileAccessData structs during TaskHost packet deserialization through interface boxing and crashed in FileAccessManager.ReportFileAccess when replaying a null path.

The ProjectCachePlugin itself was inactive, so this was not a cache lookup or materialization race. The engine defect is tracked by dotnet/msbuild#14824.

This PR therefore keeps cache graph and cache-specific sign/pack operations process-based. Ordinary Windows fallback builds use -mt without importing cache support packages; Linux and macOS ordinary builds also use -mt.

Conclusion

Multithreaded MSBuild provides a modest end-to-end improvement on Windows: 4.8% locally and 4.0% in comparable PR CI, with no corrected-run failures. Linux results are consistent with a smaller improvement, while current macOS variance is too high for a precise estimate. Cache population and multithreaded execution should remain separate experiments until the TaskHost file-access serialization defect is fixed and their combined topology can be evaluated independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI balanced review requested due to automatic review settings August 25, 2026 11:31

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Enables multithreaded MSBuild for local Windows builds and public CI builds while leaving official builds unchanged.

Changes:

  • Defaults local PowerShell builds to multithreaded mode.
  • Enables multithreading across public Windows, Linux, and macOS CI paths.
  • Identified missing equivalent default for local Unix builds.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
eng/build.ps1Configures the local PowerShell default.
azure-pipelines.ymlEnables multithreading in public CI build paths.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadeng/build.ps1
Comment on lines +86 to +87
if (-not $PSBoundParameters.ContainsKey("msbuildMultiThreaded")) {
$PSBoundParameters["msbuildMultiThreaded"] = -not $ci
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Build Failure Analysis

Summary — Enabling MSBuild's new -msbuildMultiThreaded (-mt) mode in this PR triggers a NullReferenceException inside the ResolveFileAccesses MSBuild task shipped by the Microsoft.MSBuildCache.SharedCompilation package, failing every Windows build leg (Release and Debug); the Linux/macOS legs (which don't hit this code path) compiled cleanly.

Root cause: -mt is incompatible with Microsoft.MSBuildCache.SharedCompilation's ResolveFileAccesses task

This PR adds -msbuildMultiThreaded/-mt to the CI invocations in azure-pipelines.yml and threads the corresponding parameter through eng/build.ps1. On both Windows Release and Windows Debug legs, MSBuild fails 13 projects (e.g. Microsoft.Testing.Platform, TestFramework.SourceGeneration, TestFramework, MSTest.Analyzers, MSTest.SourceGeneration, MSTest.Sdk) with the identical stack:

MSB4018: The "ResolveFileAccesses" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Build.FileAccesses.FileAccessManager.ReportFileAccess(FileAccessData fileAccessData, Int32 nodeId)
at Microsoft.Build.BackEnd.TaskHostTask.HandleTaskHostTaskComplete(TaskHostTaskComplete taskHostTaskComplete)
at Microsoft.Build.BackEnd.TaskHostTask.HandlePacket(INodePacket packet, Boolean& taskFinished)
at Microsoft.Build.BackEnd.TaskHostTask.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()

thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9 in the ResolveCoreCompileFileAccesses target of the restored .packages\microsoft.msbuildcache.sharedcompilation\0.1.328-preview package. This repo already uses that MSBuildCache package for shared/out-of-proc compilation, which relies on MSBuild's TaskHostTask/FileAccessManager file-access-reporting plumbing (used for build-output caching). Turning on -mt changes MSBuild's node/threading model for concurrent task execution and file-access reporting; FileAccessManager.ReportFileAccess null-refs when it receives a completion callback for a node id it apparently doesn't have registered under multi-threaded execution — an incompatibility between this MSBuildCache version's file-access hook and -mt mode, not a defect in TestFx's own source.

Evidence that isolates -mt as the trigger:

  • Only the Windows legs that pass -msbuildMultiThreaded:$true/-mt (Windows Release, Windows Debug) fail; the Windows application-model acceptance leg, both Linux legs, and both macOS legs built cleanly.
  • Every failing project fails at the exact same target/task/line (ResolveCoreCompileFileAccessesResolveFileAccesses, SharedCompilation.targets:9) — one root cause fanning out across 13 projects, not 13 independent bugs.
  • No C#/analyzer compiler errors were reported anywhere in either failing leg — the actual compile never runs; the crash happens in the file-access-tracking wrapper around the compile task itself.

Affected projects (13 total, identical stack; representative subset)

  • src/Platform/Microsoft.Testing.Platform/Microsoft.Testing.Platform.csproj
  • src/Platform/Microsoft.Testing.Platform.ServerMode.Client.Sources/...csproj
  • src/TestFramework/TestFramework.SourceGeneration/TestFramework.SourceGeneration.csproj
  • src/TestFramework/TestFramework/TestFramework.csproj (Debug leg only)
  • src/Analyzers/MSTest.Analyzers/MSTest.Analyzers.csproj
  • src/Analyzers/MSTest.SourceGeneration/MSTest.SourceGeneration.csproj
  • src/Analyzers/MSTest.GlobalConfigsGenerator/MSTest.GlobalConfigsGenerator.csproj
  • src/Package/MSTest.Sdk/MSTest.Sdk.csproj
  • test/IntegrationTests/TestAssets/SampleProjectForAssemblyResolution/...csproj
  • samples/CtrfPlayground/XunitMtp/XunitMtp.csproj

Suggested fix

This is a build-infrastructure/tooling incompatibility, not a TestFx source-code bug, so it falls outside this workflow's automated fix-commit scope (limited to src//test/; eng/build.ps1 and azure-pipelines.yml are both excluded, and the fix is not a mechanical rename provable from a compiler error anyway). Two viable directions for a maintainer:

  1. Don't enable -mt on legs where Microsoft.MSBuildCache.SharedCompilation is active until that package (currently pinned at 0.1.328-preview) ships a fix for -mt compatibility — i.e. drop the newly-added -msbuildMultiThreaded lines for the Windows Release/Debug stages in azure-pipelines.yml, or gate them behind whether MSBuildCache is enabled for that leg.
  2. If -mt is required for this PR's goal, file/check for an upstream issue against Microsoft.MSBuildCache for -mt (multi-threaded node) compatibility with its ResolveFileAccesses/FileAccessManager file-access-tracking hook, and bump the package once fixed.

Since the crash originates inside a third-party MSBuild extension package rather than TestFx source, no inline code suggestion is offered — reverting or gating the newly-added -mt flags on the affected legs is the pragmatic short-term mitigation.


Build overview (Windows Release leg)
Build: FAILED
Duration: 156.2s
MSBuild: 18.10.0-1.26379.9+c88db8eb0
Projects: 74 Errors: 13 Warnings: 1
All MSBuild errors (13, identical across Windows Release + Windows Debug legs)
CodeTaskTargetRoot message
MSB4018ResolveFileAccessesResolveCoreCompileFileAccessesNullReferenceException in FileAccessManager.ReportFileAccess, thrown from Microsoft.MSBuildCache.SharedCompilation.targets:9

(13 occurrences across each failing leg, one per failed project, all sharing this identical stack trace.)


🤖 Generated by the Build Failure Analysis workflow using (a href="(dev.azure.com/redacted) · commit ca552a2

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · auto · 92.4 AIC · ⌖ 1.74 AIC · ⊞ 13.3K · [◷]( · )

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings August 25, 2026 12:37

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@JanProvaznik