Profiling .NET in Production Without Killing Performance

dotnet-trace, EventPipe, and continuous profiling with minimal overhead — our observability stack for latency investigation.

Production profiling is scary until you have the right tools. Here’s how we investigate latency without restarting services.

Continuous Profiling with dotnet-monitor

dotnet-monitor collect \
  --process-id 1234 \
  --duration 00:01:00 \
  --profile cpu \
  --output /tmp/trace.nettrace

Overhead: <1% CPU for 60-second captures. Safe for production.

Analyzing Traces

dotnet-trace report trace.nettrace \
  --top-n 20 \
  --inclusive \
  --format json

Look for:

  • GC pauses > 50ms
  • Thread pool starvation (long Wait times)
  • Sync-over-async (Task.Wait() in async code)

Our Alerting Stack

  1. P99 latency breach → auto-trigger 60s trace
  2. Trace uploaded to shared storage
  3. Slack notification with flame graph link
  4. On-call investigates within 15 minutes

Quick Wins We Found

IssueImpactFix
Sync JSON serialization+40ms P99Source generators
Missing DB index+200ms on one endpointAdded composite index
Large object heap pressureGC pauses every 30sObject pooling for buffers

profiling , observability , dotnet · .NET , Linux

More in Performance