Skip to content
Development
Skill

/build-perf-diagnostics

Diagnose MSBuild build performance bottlenecks using binary log analysis. USE FOR: identifying why builds are slow by analyzing binlog performance summaries, detecting ResolveAssemblyReference (RAR) taking >5s, Roslyn analyzers consuming >30% of Csc time, single targets

From plugin
dotnet-skills
5.1k96 skills16 agents
Install
$ npx -y skills add dotnet/skills --skill build-perf-diagnostics --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/build-perf-diagnostics

Context preview

The summary Claude sees to decide when to auto-load this skill.

Diagnose MSBuild build performance bottlenecks using binary log analysis. USE FOR: identifying why builds are slow by analyzing binlog performance summaries, detecting ResolveAssemblyReference (RAR) taking >5s, Roslyn analyzers consuming >30% of Csc time, single targets

SKILL.md

build-perf-diagnostics.SKILL.md
name: build-perf-diagnostics
description: "Diagnose MSBuild build performance bottlenecks using binary log analysis. USE FOR: identifying why builds are slow by analyzing binlog performance summaries, detecting ResolveAssemblyReference (RAR) taking >5s, Roslyn analyzers consuming >30% of Csc time, single targets dominating >50% of build time, node utilization below 80%, excessive Copy tasks, NuGet restore running every build. Covers timeline analysis, Target/Task Performance Summary interpretation, and 7 common bottleneck categories. Use after build-perf-baseline has established measurements. DO NOT USE FOR: establishing initial baselines (use build-perf-baseline first), fixing incremental build issues (use incremental-build), parallelism tuning (use build-parallelism), non-MSBuild build systems."
license: MIT

Performance Analysis Methodology

1. **Generate a binlog**: `dotnet build /bl:{} -m` 2. Use the **binlog MCP server** (`Microsoft.AITools.BinlogMcp`, exposed under the `binlog` MCP namespace) which is bundled with this plugin

Alternate flow when MCP is unavailable: binlog replay to text logs

1. **Generate a binlog**: `dotnet build /bl:{} -m` 2. **Replay to diagnostic log with performance summary**:

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

3. **Read the performance summary** (at the end of `full.log`):

   grep "Target Performance Summary\|Task Performance Summary" -A 50 full.log

4. **Find expensive targets and tasks**: The PerformanceSummary section lists all targets/tasks sorted by cumulative time 5. **Check for node utilization**: grep for scheduling and node messages

   grep -i "node.*assigned\|building with\|scheduler" full.log | head -30

6. **Check analyzers**: grep for analyzer timing

   grep -i "analyzer.*elapsed\|Total analyzer execution time\|CompilerAnalyzerDriver" full.log

Key Metrics and Thresholds

  • **Build duration**: what's "normal" — small project <10s, medium <60s, large <5min
  • **Node utilization**: ideal is >80% active time across nodes. Low utilization = serialization bottleneck
  • **Single target domination**: if one target is >50% of build time, investigate
  • **Analyzer time vs compile time**: analyzers should be <30% of Csc task time. If higher, consider removing expensive analyzers
  • **RAR time**: ResolveAssemblyReference >5s is concerning. >15s is pathological

Common Bottlenecks

1. ResolveAssemblyReference (RAR) Slowness

  • **Symptoms**: RAR taking >5s per project
  • **Root causes**: too many assembly references, network-based reference paths, large assembly search paths
  • **Fixes**: reduce reference count, use `<DesignTimeBuild>false</DesignTimeBuild>` for RAR-heavy analysis, set `<ResolveAssemblyReferencesSilent>true</ResolveAssemblyReferencesSilent>` for diagnostic
  • **Advanced**: `<DesignTimeBuild>` and `<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>`
  • **Key insight**: RAR runs unconditionally even on incremental builds because users may have installed targeting packs or GACed assemblies (see dotnet/msbuild#2015). With .NET Core micro-assemblies, the reference count is often very high.
  • **Reduce transitive references**: Set `<DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>` to avoid pulling in the full transitive closure (note: projects may need to add direct references for any types they consume). Use `ReferenceOutputAssembly="false"` on ProjectReferences that are only needed at build time (not API surface). Trim unused PackageReferences.

2. Roslyn Analyzers and Source Generators

  • **Symptoms**: Csc task takes much longer than expected for file count (>2× clean compile time)
  • **Diagnosis**: Check the Task Performance Summary in the replayed log for Csc task time; grep for analyzer timing messages; compare Csc duration with and without analyzers (`/p:RunAnalyzers=false`)
  • **Fixes**:
  • Conditionally disable in dev: `<RunAnalyzers Condition="'$(ContinuousIntegrationBuild)' != 'true'">false</RunAnalyzers>`
  • Per-configuration: `<RunAnalyzers Condition="'$(Configuration)' == 'Debug'">false</RunAnalyzers>`
  • Code-style only: `<EnforceCodeStyleInBuild Condition="'$(ContinuousIntegrationBuild)' == 'true'">true</EnforceCodeStyleInBuild>`
  • Remove genuinely redundant analyzers from inner loop
  • Severity config in .editorconfig for less critical rules
  • **Key principle**: Preserve analyzer enforcement in CI. Never just "remove" analyzers — configure them conditionally.
  • **GlobalPackageReference**: Analyzers added via `GlobalPackageReference` in `Directory.Packages.props` apply to ALL projects. Consider if test projects need the same analyzer set as production code.
  • **EnforceCodeStyleInBuild**: When set to `true` in `Directory.Build.props`, forces code-style analysis on every build. Should be conditional on CI environment (`ContinuousIntegrationBuild`) to avoid slowing dev inner loop.

3. Serialization Bottlenecks (Single-threaded targets)

  • **Symptoms**: Performance summary shows most build time concentrated in a single project; diagnostic log shows idle nodes while one works
  • **Common culprits**: targets without proper dependency declaration, single project on critical path
  • **Fixes**: split large projects, optimize the critical path project, ensure proper `BuildInParallel`

4. Excessive File I/O (Copy tasks)

  • **Symptoms**: Copy task shows high aggregate time
  • **Root causes**: copying thousands of files, copying across network drives, Copy task unintentionally running once per item (per-file) instead of as a single batch (see dotnet/msbuild#12884)
  • **Fixes**: use hardlinks (`<CreateHardLinksForCopyFilesToOutputDirectoryIfPossible>true</CreateHardLinksForCopyFilesToOutputDirectoryIfPossible>`), reduce CopyToOutputDirectory items, use `<UseCommonOutputDirectory>true</UseCommonOutputDirectory>` when appropriate, set `<SkipCopyUnchangedFile
Read more
Ships withdotnet-skills

This repository contains the .NET team's curated set of core skills and custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io. 📊 Dashboard - Accuracy and efficiency scoring trends for contained plugins (

Get the whole plugin

Other skills on dotnet-skills.