Generated banner for Build Parallelism
Generated logo for Build Parallelism

Build Parallelism

.NET (Microsoft)OfficialPublished by .NET (Microsoft)

  • Skill
  • Research and analysis
  • Software development
  • MIT
  • No issues found

From the author

Analyze MSBuild scheduling across at least two distinct projects in a solution/filter/Build.proj. USE FOR: measured idle workers, -m not scaling, serial ProjectReference critical paths, graph builds, MSBuild Projects-list scheduling. DO NOT USE FOR: duplicate executions or invariant-generation races (find-repeated-work-within-one-build), non-MSBuild systems.
— the description by .NET (Microsoft)

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured approach to diagnosing slow parallel builds in MSBuild environments. It focuses on identifying the critical path within a project dependency graph, which often prevents effective scaling regardless of available CPU cores. By leveraging binlogs and performance summaries, users can pinpoint serial bottlenecks, optimize project references, and configure MSBuild for better parallel execution.

What it does

  • Provides a checklist to identify why parallel builds are underperforming.
  • Explains how to analyze binlogs to find the critical path in project dependencies.
  • Offers strategies to flatten dependency graphs and optimize ProjectReference usage.
  • Details the use of graph build mode for improved scheduling.
  • Guides users on configuring MSBuild worker nodes via maxcpucount.
  • Outlines methods for analyzing build performance using both MCP tools and text-log replays.

When to use it

  • When a build is taking longer than expected despite having multiple CPU cores available.
  • When you suspect a serial dependency chain is blocking parallel execution.
  • When you need to optimize large solutions with many projects.
  • When you want to verify if MSBuild is effectively utilizing all available worker nodes.

Advantages

  • Targets the root cause of build slowness rather than just increasing CPU count.
  • Provides actionable steps to reduce build times through dependency graph optimization.
  • Includes clear instructions for both modern binlog analysis and traditional log replay.
  • Helps distinguish between configuration issues and architectural bottlenecks.

Usage examples

“Why is my build not using all my CPU cores?”
The agent will guide you to check your binlog for serial dependency chains and confirm if /maxcpucount is correctly configured.
“How do I find the bottleneck in my MSBuild project?”
The agent will instruct you to replay your binlog with performance summary flags to identify the longest project chains.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/dotnet/build-parallelism/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip build-parallelism.zip -d .agents/skills

Documentation by .NET (Microsoft)

Diagnose a slow parallel build (start here)

Work this checklist in order — it targets the usual root cause (a serial dependency chain that no number of cores can parallelize):

  1. Check how many worker nodes actually built the solution. Capture a binlog with dotnet build /bl:{} (PowerShell: dotnet build '-bl:{}') and inspect the node timeline to see whether more than one node ran. Every dotnet CLI command built on the SDK's MSBuild-forwarding path (build, msbuild, test, pack, publish, etc.) enables /maxcpucount (multiple nodes) by default; -m:1 forces a single node. A direct MSBuild.exe invocation is sequential by default, so pass -m explicitly to enable parallel worker nodes there.

  2. Find the critical path. From the binlog, read per-project timings and the node timeline. If total build time ≈ the sum of the projects on one dependency chain, that chain — not CPU count — is the bottleneck.

  3. Name the chain explicitly, e.g. Core → Api → Web → Tests. A long serial chain stays serial no matter how large -m is, because each project waits on its predecessor.

  4. Look for unnecessary ProjectReference edges that lengthen the chain — a reference that only needs build order (not the output assembly), or one that could be a PackageReference, forces serialization it doesn't need.

  5. Recommend flattening: break false dependencies so independent projects build concurrently, and consider /graph for better scheduling.

MSBuild Parallelism Model

  • /maxcpucount (or -m): number of worker nodes (processes)

  • Every dotnet CLI command (build, msbuild, test, pack, publish, etc.) passes /maxcpucount by default via the SDK's shared MSBuild-forwarding path; -m:1 overrides it with one node

  • A direct MSBuild.exe invocation is sequential by default and requires an explicit -m

  • Recommended: -m without a number = use all logical processors

  • Each node builds one project at a time

  • Projects are scheduled based on dependency graph

Project Dependency Graph

  • MSBuild builds projects in dependency order (topological sort)

  • Critical path: longest chain of dependent projects determines minimum build time

  • Bottleneck: if project A depends on B, C, D and B takes 60s while C and D take 5s, B is the bottleneck

  • Diagnosis: replay binlog to diagnostic log with performancesummary and check Project Performance Summary — shows per-project time; grep for node.*assigned to check scheduling

  • Wide graphs (many independent projects) parallelize well; deep graphs (long chains) don't

Graph Build Mode (/graph)

  • dotnet build /graph or msbuild /graph

  • What it changes: MSBuild constructs the full project dependency graph BEFORE building

  • Benefits: better scheduling, avoids redundant evaluations, enables isolated builds

  • Limitations: all projects must use <ProjectReference> (no programmatic MSBuild task references)

  • When to use: large solutions with many projects, CI builds

  • When NOT to use: projects that dynamically discover references at build time

Optimizing Project References

  • Reduce a <ProjectReference> only after proving it is unnecessary; a slow but valid dependency must stay in the graph

  • Use <ProjectReference ... SkipGetTargetFrameworkProperties="true"> to avoid extra evaluations

  • <ProjectReference ... ReferenceOutputAssembly="false"> for build-order-only dependencies

  • Consider if a ProjectReference should be a PackageReference instead (pre-built NuGet)

  • Use solution filters (.slnf) to build subsets of the solution

BuildInParallel

  • <MSBuild Projects="@(ProjectsToBuild)" BuildInParallel="true" /> in custom targets

  • Without BuildInParallel="true", MSBuild task batches projects sequentially

  • Ensure /maxcpucount > 1 for this to have effect

Multi-threaded MSBuild Tasks

  • Individual tasks can run multi-threaded within a single project build

  • Tasks implementing IMultiThreadableTask can run on multiple threads

  • Tasks must declare thread-safety via [MSBuildMultiThreadableTask]

Analyzing Parallelism with Binlog

Primary: binlog MCP (preferred)

Use the binlog MCP server (Microsoft.AITools.BinlogMcp, exposed under the binlog MCP namespace):

  1. Use expensive_projects tool → find the slowest projects and compare individual vs total build time

  2. Use expensive_targets tool → find bottleneck targets

  3. Use project_target_times tool → drill into a specific project's target-level timing

  4. Ideal: build time should be much less than sum of project times (parallelism)

  5. If build time ≈ sum of project times: too many serial dependencies, or one slow project blocking others

Fallback: text-log replay (when MCP is unavailable)

Step-by-step:

  1. Replay the binlog: dotnet msbuild build.binlog -noconlog -fl "-flp:v=diag;logfile=full.log;performancesummary"

  2. Check Project Performance Summary at the end of full.log

  3. Ideal: build time should be much less than sum of project times (parallelism)

  4. If build time ≈ sum of project times: too many serial dependencies, or one slow project blocking others

  5. grep 'Target Performance Summary' -A 30 full.log → find the bottleneck targets

  6. Consider splitting large projects or optimizing the critical path

CI/CD Parallelism Tips

  • Use -m in CI (many CI runners have multiple cores)

  • Consider splitting solution into build stages for extreme parallelism

  • Use build caching (NuGet lock files, deterministic builds) to avoid rebuilding unchanged projects

  • dotnet build /graph works well with structured CI pipelines

Files

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an MCP server, Needs Node.js

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
.NET (Microsoft)
Publisher
.NET (Microsoft) (Official)
Source
dotnet/skills · plugins/dotnet-msbuild/skills/build-parallelism · commit 96c3d68
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by .NET (Microsoft).

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download build-parallelism.zip