Performance Considerations for dotnet/skills Plugins: A Complete Guide to Optimizing .NET Builds and Runtime
Performance considerations for dotnet/skills plugins center on MSBuild evaluation efficiency, incremental build correctness, and runtime optimization patterns across .NET MAUI, EF Core, and microbenchmarking scenarios.
The dotnet/skills repository provides markdown-driven autonomous skills that agents invoke to solve specific .NET development problems. Understanding the performance considerations for dotnet/skills plugins helps developers diagnose slow builds, optimize UI rendering, and implement proper benchmarking practices across the entire plugin ecosystem.
MSBuild Evaluation and Build Performance
MSBuild performance dominates the plugin guidance because build speed directly impacts developer productivity. The dotnet-msbuild plugin contains multiple skills dedicated to identifying and resolving compilation bottlenecks.
Minimizing Evaluation Overhead
Expensive evaluation patterns cause significant slowdowns during project loading. According to the source code in /plugins/dotnet-msbuild/skills/eval-performance/SKILL.md, avoid expensive glob patterns like **/node_modules/** and deep import chains that force repeated disk I/O. Property functions that perform file-system calls—such as $([System.IO.File]::ReadAllText(...))—should be eliminated entirely.
Use DefaultItemExcludes to prune large directories from wildcard searches and limit import depth to reduce evaluation time.
Enabling Incremental Builds with Inputs and Outputs
Missing Inputs and Outputs declarations on custom targets force unnecessary rebuilds. As specified in /plugins/dotnet-msbuild/skills/incremental-build/SKILL.md, every target must declare both attributes to support incremental compilation:
<Target Name="GenerateFoo"
Inputs="@(FooInput)"
Outputs="@(FooOutput)">
<Message Text="Generating Foo…" />
<!-- generation logic -->
</Target>
Avoid volatile properties like timestamps or GUIDs that change between builds, and register all file writes via the FileWrites item group to ensure proper change tracking.
Leveraging the MSBuild Server
CLI builds are slower than IDE builds because Visual Studio maintains a long-lived MSBuild process while the CLI starts fresh each time. Enable server-side caching by setting the environment variable before building:
export MSBUILDUSESERVER=1
dotnet build
This configuration, documented in /plugins/dotnet-msbuild/skills/msbuild-server/SKILL.md, reuses evaluation results across invocations to eliminate startup overhead.
Diagnosing Build Bottlenecks with Binary Logs
The binary‑log‑first workflow underpins all performance diagnostics in the dotnet/skills ecosystem. Capture a baseline binary log to enable deterministic replay without affecting the original build:
dotnet build -bl:build.binlog
Analyze the log with performance summary output to identify specific bottlenecks:
dotnet msbuild build.binlog -noconlog \
-fl -flp:v=diag;logfile=full.log;performancesummary
This approach, detailed in /plugins/dotnet-msbuild/skills/build-perf-diagnostics/SKILL.md, provides lossless capture of MSBuild execution for precise analysis.
Parallelism and Resource Utilization
Under-utilized CPU cores indicate missed optimization opportunities. The /plugins/dotnet-msbuild/skills/build-parallelism/SKILL.md file recommends using the -maxcpucount switch to enable parallel project builds.
Inspect the "Project Performance Summary" section of your binary log to verify proper node assignment. Project dependencies that create artificial serialization chains should be refactored to allow concurrent compilation where possible.
Application Runtime Performance
Beyond build optimization, dotnet/skills plugins address runtime performance in .NET MAUI applications and data access layers.
.NET MAUI UI Rendering Optimization
The migration from ListView to CollectionView provides significant rendering improvements. According to /plugins/dotnet-maui/skills/maui-collectionview/SKILL.md, use CollectionView with MeasureFirstItem sizing for uniform collections to reduce layout calculations.
Set OverscanCount explicitly when working with virtualized lists to control the number of items rendered outside the visible viewport. The default value changed from 3 to 15 in Blazor Virtualize between versions, making explicit configuration critical for predictable performance.
Entity Framework Core Query Tuning
Common EF Core performance traps include N+1 queries and inappropriate change tracking. The /plugins/dotnet-data/skills/optimizing-ef-core-queries/SKILL.md file recommends three specific optimizations:
- Eager loading: Use
Includeto fetch related data in single round-trips. - No-tracking queries: Apply
AsNoTrackingfor read-only scenarios to eliminate change-tracking overhead. - Compiled queries: Cache query plans for frequently executed queries.
Implement compiled queries for hot paths:
static readonly Func<MyDbContext, int, IQueryable<Customer>> GetCustomersByAge
= EF.CompileQuery((MyDbContext ctx, int age) =>
ctx.Customers.Where(c => c.Age == age));
using var ctx = new MyDbContext();
var result = GetCustomersByAge(ctx, 30).ToList();
Benchmarking and Diagnostics
Micro-benchmarking Best Practices
Accurate performance measurement requires rigorous methodology. The /plugins/dotnet-diag/skills/microbenchmarking/SKILL.md file emphasizes using BenchmarkDotNet with [MemoryRandomization] to mitigate cache effects.
Separate benchmark jobs for different GC modes and JIT configurations ensure measurements reflect real-world variants. Keep each benchmark case idempotent and independent to prevent state mutation from skewing results:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
public class MyBenchmarks
{
[Params(100, 1_000, 10_000)]
public int Size;
[Benchmark]
public void Loop()
{
var sum = 0;
for (int i = 0; i < Size; i++) sum += i;
}
}
public class Program
{
public static void Main()
=> BenchmarkRunner.Run<MyBenchmarks>();
}
Run benchmarks in Release configuration:
dotnet run -c Release
Runtime Configuration Management
Configuration values affecting performance must be pinned explicitly. The /plugins/dotnet-upgrade/skills/migrate-dotnet10-to-dotnet11/SKILL.md file highlights that default OverscanCount changes between framework versions can unexpectedly degrade UI performance.
Async-only APIs (such as Cosmos DB clients) require async propagation throughout the call stack. Sync-over-async patterns cause thread pool starvation and deadlocks—always prefer await chains from the entry point through the data layer.
Summary
- MSBuild evaluation requires pruning large directory globs and eliminating I/O-bound property functions to reduce project load times.
- Incremental builds depend on explicit
InputsandOutputsdeclarations on all custom targets, avoiding volatile properties that force rebuilds. - MSBuild server mode (
MSBUILDUSESERVER=1) enables process reuse for CLI builds, matching IDE performance characteristics. - Binary logs provide the foundation for all build diagnostics, enabling replay with performance summaries without re-executing the build.
- CollectionView with explicit sizing strategies outperforms ListView in .NET MAUI applications, while
AsNoTrackingand compiled queries optimize EF Core data access. - BenchmarkDotNet with proper isolation and memory randomization ensures accurate micro-benchmarks across different runtime configurations.
Frequently Asked Questions
How do I enable MSBuild server mode for faster command-line builds?
Set the MSBUILDUSESERVER environment variable to 1 before running dotnet build. This enables the long-lived MSBuild process to cache evaluation results across invocations, eliminating the startup overhead present in standard CLI builds. The configuration is documented in /plugins/dotnet-msbuild/skills/msbuild-server/SKILL.md.
What causes MSBuild incremental builds to fail and rebuild unnecessarily?
Missing Inputs or Outputs attributes on custom targets force MSBuild to assume the target is always out of date. Additionally, volatile properties containing timestamps or GUIDs change between builds, invalidating the incremental cache. Declare explicit file dependencies and register outputs via the FileWrites item group to ensure proper change detection.
Why should I use CollectionView instead of ListView in .NET MAUI?
CollectionView provides superior virtualization and layout performance compared to ListView. Using MeasureFirstItem sizing strategy reduces layout measurement overhead for uniform collections, while explicit OverscanCount configuration controls memory usage during scrolling. The guidance in /plugins/dotnet-maui/skills/maui-collectionview/SKILL.md documents these specific optimization patterns.
How do I capture performance diagnostics for a slow build?
Generate a binary log using dotnet build -bl:build.binlog, then replay the log with performance summary flags: dotnet msbuild build.binlog -flp:v=diag;logfile=full.log;performancesummary. This workflow, specified in /plugins/dotnet-msbuild/skills/build-perf-diagnostics/SKILL.md, analyzes the captured execution without re-running the build, identifying specific targets and tasks consuming excessive time.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →