Guide for diagnosing and improving MSBuild project evaluation performance. USE FOR: builds slow before any compilation starts, high evaluation time in binlog analysis, expensive glob patterns walking large directories (node_modules, .git, bin/obj), deep import chains (>20 levels), preprocessed output >10K lines indicating heavy evaluation, property functions with file I/O ($([System.IO.File]::ReadAllText(...))), multiple evaluations per project. Covers the 5 MSBuild evaluation phases, glob optimization via DefaultItemExcludes, import chain analysis with /pp preprocessing. DO NOT USE FOR: compi
Start a fresh conversation. Replace the highlighted placeholders.
Use eval-performance to analyze [MSBuild binlog or timing summary], confirm whether project evaluation is the measurable bottleneck, and recommend only evidence-supported, targeted improvements.
Required inputs
[MSBuild binlog or timing summary]
User-approved starter prompt based on a pinned source version; check current skill requirements before running. Task evidence ↗
SKILL.md
name: eval-performancedescription: "Guide for diagnosing and improving MSBuild project evaluation performance. USE FOR: builds slow before any compilation starts, high evaluation time in binlog analysis, expensive glob patterns walking large directories (node_modules, .git, bin/obj), deep import chains (>20 levels), preprocessed output >10K lines indicating heavy evaluation, property functions with file I/O ($([System.IO.File]::ReadAllText(...))), multiple evaluations per project. Covers the 5 MSBuild evaluation phases, glob optimization via DefaultItemExcludes, import chain analysis with /pp preprocessing. DO NOT USE FOR: compilation-time slowness (use build-perf-diagnostics), incremental build issues (use incremental-build), non-MSBuild build systems."license: MIT
Diagnosing MSBuild Evaluation Performance
Evaluation is the work MSBuild does before any target runs — reading project
files, processing imports, expanding globs. This skill helps you find and
confirm evaluation bottlenecks. Measure first; recommend a change only when a
measurement proves it is warranted.
Confirm the problem before changing anything
Engage only when evaluation is measurably the bottleneck. Do NOT act when:
The slowness is during compilation or target execution, not evaluation.
That is not an evaluation problem — use build-perf-diagnostics instead.
The complaint is "rebuilds too much" / incremental build. Use
incremental-build instead.
You have no measurement. If no binlog or timing summary shows evaluation
is slow, gather one first (see below). Do not guess from reading project files.
A pattern below appears but evaluation is already fast. Broad globs, deep
imports, or EnableDefaultItems are only worth flagging when the numbers show
they cost real time. A project that evaluates quickly needs no change.
When a pattern is present but unmeasured, report it as an observation and let
the user decide — do not rewrite working configuration to match a "best
practice" without evidence it costs measurable evaluation time. Prefer the
smallest, most targeted change; never disable SDK defaults as a first move.
MSBuild Evaluation Phases
For a comprehensive overview of MSBuild's evaluation and execution model, see Build process overview.
Initial properties: environment variables, global properties, reserved properties
Imports and property evaluation: process <Import>, evaluate <PropertyGroup> top-to-bottom
Item evaluation: <ItemGroup> with Include, Remove, Update, glob expansion
UsingTask evaluation: register custom tasks
Key insight: evaluation happens BEFORE any targets run. Slow evaluation = slow build start even when nothing needs compiling.
Diagnosing Evaluation Performance
Primary: binlog MCP (preferred)
Use the binlog MCP server (Microsoft.AITools.BinlogMcp, exposed under the binlog MCP namespace) to analyze evaluation performance:
Use the evaluations tool to list all evaluations and their durations
Use evaluation_global_properties to check for multiple evaluations with differing global properties
Use evaluation_properties to inspect evaluated properties for a specific project+TFM
Use imports tool to analyze the import chain depth and structure
Use properties tool to check for expensive property function evaluations
Fallback: text-log replay and preprocessing (when MCP is unavailable)
Using binlog
Replay the binlog: dotnet msbuild build.binlog -noconlog -fl "-flp:v=diag;logfile=full.log"
Search for evaluation events: grep -i 'Evaluation started\|Evaluation finished' full.log
Multiple evaluations for the same project = overbuilding
Look for "Project evaluation started/finished" messages and their timestamps
Using /pp (preprocess)
dotnet msbuild -pp:full.xml MyProject.csproj
Shows the fully expanded project with ALL imports inlined
Use to understand: what's imported, import depth, total content volume
Large preprocessed output (>10K lines) = heavy evaluation
Using /clp:PerformanceSummary
Add to build command for timing breakdown
Shows evaluation time separately from target/task execution
Expensive Glob Patterns
Only pursue these remedies once a measurement shows item evaluation is slow and
the globs are the cause; a custom glob that isn't walking large trees is fine.
Globs like **/*.cs walk the entire directory tree
Default SDK globs are optimized, but custom globs may not be
Problem: globbing over node_modules/, .git/, bin/, obj/ — millions of files
Remedy: use <DefaultItemExcludes> to exclude large directories
Remedy: be specific with glob paths: src/**/*.cs instead of **/*.cs
Remedy: use <EnableDefaultItems>false</EnableDefaultItems> only as a last resort (loses SDK defaults) — prefer the two options above first
Check: grep for Compile items in the diagnostic log → if Compile items include unexpected files, globs are too broad