npx skills add ...
npx skills add dotnet/skills --skill build-perf-baseline
Establish build performance baselines and apply systematic optimization techniques. USE FOR: diagnosing slow builds, establishing before/after measurements (cold, warm, no-op scenarios), applying optimization strategies like static graph builds, artifacts output, and dependency graph trimming. Start here before diving into build-perf-diagnostics, incremental-build, or build-parallelism. DO NOT USE FOR: non-MSBuild build systems, detailed bottleneck analysis (use build-perf-diagnostics after baselining).
npx skills add dotnet/skills --skill build-perf-baseline
Before optimizing a build, you need a baseline. Without measurements, optimization is guesswork. This skill covers how to establish baselines and apply systematic optimization techniques.
Related skills:
build-perf-diagnostics — binlog-based bottleneck identificationincremental-build — Inputs/Outputs and up-to-date checksbuild-parallelism — parallel and graph build tuningeval-performance — glob and import chain optimizationMeasure three scenarios to understand where time is spent:
No previous build output exists. Measures the full end-to-end time including restore, compilation, and all targets.
Build output exists, some files have changed. Measures how well incremental build works.
Build output exists, nothing has changed. This should be nearly instant. If it's slow, incremental build is broken.
| Scenario | Expected Behavior |
|---|---|
| Cold build | Full compilation, all targets run. This is your absolute baseline |
| Warm build | Only changed projects recompile. Time proportional to change scope |
| No-op build | < 5 seconds for small repos, < 30 seconds for large repos. All compilation targets should report "Skipping target — all outputs up-to-date" |
Red flags:
incremental-build skill)Record baselines in a structured way before and after optimization:
The UseArtifactsOutput feature (introduced in .NET 8) changes the output directory structure to avoid bin/obj clash issues and enable better caching.
artifacts/ directory to cache/restore in CIartifacts/Deterministic builds produce byte-for-byte identical output given the same inputs. This is essential for build caching and reproducibility.
Reducing unnecessary project references shortens the critical path and reduces what gets built.
When you need a project to build before yours but don't need its assembly output:
When a dependency is an internal implementation detail that shouldn't flow to consumers:
For explicit-only dependency management (extreme measure for very large repos):
Caution: This requires all dependencies to be listed explicitly. Only use in large repos where transitive closure is causing excessive rebuilds.
/graph)Static graph mode evaluates the entire project graph before building, enabling better scheduling and isolation.
| Scenario | Recommendation |
|---|---|
| Large multi-project solution (20+ projects) | ✅ Try /graph — may see significant parallelism gains |
| Small solution (< 5 projects) | ❌ Overhead of graph evaluation outweighs benefits |
| CI builds | ✅ Graph builds are more predictable and parallelizable |
| Local development | ⚠️ Test both — may or may not help depending on project structure |
Graph build requires that all ProjectReference items are statically determinable (no dynamic references computed in targets). If graph build fails:
Fix: Ensure all ProjectReference items are declared in <ItemGroup> outside of targets (not dynamically computed inside <Target> blocks).
In a binlog, look for:
Use grep 'Target Performance Summary' -A 30 full.log in binlog analysis to see build node utilization.
The critical path is the longest chain of dependent projects. To shorten it:
ReferenceOutputAssembly="false" for build-order-only dependenciesAlways start with a binlog:
Then use the build-perf-diagnostics skill and binlog tools for systematic bottleneck identification.