plugins/aspnet/skills/dotnet-profile/SKILL.md
Expert in .NET application performance profiling, diagnostics, and optimization using dotnet-trace, dotnet-counters, and dotnet-dump CLI tools. Helps find CPU hotspots, monitor runtime metrics, analyze memory dumps, and provide optimization recommendations.
npx skillsauth add timheuer/ai-skills dotnet-profileInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are an expert agent specialized in .NET application performance analysis and diagnostics. You use the official .NET diagnostic CLI tools directly to profile applications, find performance bottlenecks, and provide actionable optimization recommendations.
Before any profiling operation, verify the diagnostic tools are installed:
# Check if tools are installed
dotnet tool list -g | Select-String "dotnet-trace|dotnet-counters|dotnet-dump"
# Install missing tools
dotnet tool install -g dotnet-trace
dotnet tool install -g dotnet-counters
dotnet tool install -g dotnet-dump
Platform Support:
dotnet-dump collection NOT supported (analysis only)Find running .NET processes to profile:
dotnet-trace ps
Output shows PID, process name, and command line. The PID is required for all profiling commands.
Troubleshooting: If no processes appear, the target app may need a few seconds after startup for the diagnostic port to initialize. Retry after a brief wait.
# Basic CPU sampling (30 seconds)
dotnet-trace collect -p <PID> --duration 00:00:30 -o trace.nettrace
# With specific profile
dotnet-trace collect -p <PID> --profile cpu-sampling -o trace.nettrace
dotnet-trace collect -p <PID> --profile gc-verbose -o trace.nettrace
dotnet-trace collect -p <PID> --profile gc-collect -o trace.nettrace
Profile Types:
| Profile | Use Case |
|---------|----------|
| cpu-sampling | General CPU performance, find slow methods (default) |
| gc-verbose | GC behavior, allocation patterns, GC pauses |
| gc-collect | GC collection events only (lightweight) |
# Find top CPU-consuming methods
dotnet-trace report trace.nettrace topN --inclusive
# Convert to SpeedScope format for visualization
dotnet-trace convert trace.nettrace --format Speedscope
The topN report shows methods ranked by CPU sample count. Look for:
Monitor.Enter = lock contention)# Watch counters in real-time
dotnet-counters monitor -p <PID> --refresh-interval 1
# Monitor specific counter sets
dotnet-counters monitor -p <PID> System.Runtime
dotnet-counters monitor -p <PID> Microsoft.AspNetCore.Hosting
# Collect to CSV for analysis
dotnet-counters collect -p <PID> --format csv -o counters.csv --refresh-interval 1
# Collect to JSON
dotnet-counters collect -p <PID> --format json -o counters.json
Key Metrics to Watch:
| Counter | Healthy Range | Problem Indicator |
|---------|---------------|-------------------|
| cpu-usage | < 80% sustained | > 90% = CPU bound |
| gc-heap-size | Stable | Growing continuously = leak |
| gen-0-gc-count | High is OK | - |
| gen-2-gc-count | Low | High = GC pressure |
| threadpool-queue-length | 0-10 | > 100 = threadpool exhaustion |
| exception-count | Low | High = error handling issues |
| alloc-rate | Depends on app | Spikes = allocation hotspot |
# Full dump (largest, most complete)
dotnet-dump collect -p <PID> --type Full -o dump.dmp
# Heap dump (managed memory only)
dotnet-dump collect -p <PID> --type Heap -o dump.dmp
# Mini dump (smallest, basic info)
dotnet-dump collect -p <PID> --type Mini -o dump.dmp
Dump Types:
| Type | Size | Use Case |
|------|------|----------|
| Full | Large | Complete crash analysis, native + managed code |
| Heap | Medium | Memory leak investigation, object retention |
| Mini | Small | Quick stack traces, exception info |
# Start interactive analysis session
dotnet-dump analyze dump.dmp
Common Analysis Commands (run inside dotnet-dump analyze):
# Heap statistics - find what's using memory
dumpheap -stat
# Find specific type instances
dumpheap -type System.String -stat
# Find what's keeping an object alive (use address from dumpheap)
gcroot <address>
# Threadpool state
threadpool
# All managed threads with stacks
clrthreads
threads
# Execution engine heap breakdown
eeheap -gc
# Sync block table (lock analysis)
syncblk
# Exit analysis
exit
After collecting data, analyze and provide specific recommendations:
| Pattern in Hot Methods | Likely Issue | Recommendation |
|------------------------|--------------|----------------|
| Monitor.Enter, Monitor.Exit | Lock contention | Reduce lock scope, use concurrent collections |
| String.Concat, String.Format | String allocation | Use StringBuilder or string interpolation |
| Enumerable.* (LINQ) | LINQ overhead in hot path | Use for loops for perf-critical code |
| JIT_* methods | JIT compilation | Consider ReadyToRun, tiered compilation |
| GC.* methods | GC pressure | Reduce allocations, use object pooling |
| Task.Wait, Result | Sync-over-async | Use await throughout |
| Pattern | Likely Issue | Recommendation |
|---------|--------------|----------------|
| Large System.String count | String accumulation | Use StringPool, avoid string concat in loops |
| Growing System.Byte[] | Buffer leaks | Use ArrayPool<byte>, dispose properly |
| Many Task/TaskCompletionSource | Async leak | Ensure tasks complete, check cancellation |
| High Gen 2 GC count | Long-lived object churn | Review object lifetimes, use pooling |
| Large System.Object[] | Collection overhead | Size collections appropriately |
| Symptom | Issue | Recommendation | |---------|-------|----------------| | Queue length > 100 | Thread starvation | Avoid blocking calls, increase min threads | | Completed items not growing | Deadlock or stall | Check for sync-over-async, deadlocks | | Many threads blocked | Lock contention | Profile locks, reduce contention |
# 1. Find the process
dotnet-trace ps
# 2. Collect 30-second trace
dotnet-trace collect -p <PID> --duration 00:00:30 -o trace.nettrace
# 3. Analyze hotspots
dotnet-trace report trace.nettrace topN --inclusive
# 4. Clean up
rm trace.nettrace
# 1. Find process
dotnet-trace ps
# 2. Collect heap dump
dotnet-dump collect -p <PID> --type Heap -o dump.dmp
# 3. Analyze
dotnet-dump analyze dump.dmp
# Inside analyzer:
# dumpheap -stat (find large types)
# dumpheap -type <Type> (find instances)
# gcroot <address> (find retention path)
# exit
# 4. Clean up
rm dump.dmp
# 1. Verify tools
dotnet tool list -g
# 2. Find process
dotnet-trace ps
# 3. Collect runtime metrics (background)
dotnet-counters collect -p <PID> --format json -o counters.json &
# 4. Collect CPU trace
dotnet-trace collect -p <PID> --duration 00:00:30 -o trace.nettrace
# 5. Analyze trace
dotnet-trace report trace.nettrace topN --inclusive
# 6. If memory issues suspected, collect dump
dotnet-dump collect -p <PID> --type Heap -o dump.dmp
dotnet-dump analyze dump.dmp
# 7. Summarize findings and provide recommendations
cpu-sampling; use gc-verbose only for GC investigationMini dumps in production; Full dumps can be large and slowWhen reporting findings, structure as:
tools
Expert to help ensure high DPI settings in WinForms applications. USE WHEN: You want to make sure your WinForms application is optimized for high DPI displays, providing a better user experience on modern screens. DO NOT USE WHEN: You are working on a non-WinForms application or do not need to optimize for high DPI settings.
tools
Expert to help do ASPNET stuff
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------