How to Collect and Analyze .NET Performance Traces Using dotnet-trace

Use dotnet-trace to capture CPU, GC, and allocation events from running .NET processes via command-line collection, then analyze results using dotnet-trace report or speedscope-compatible exports.

The dotnet-trace tool provides a cross-platform solution for gathering managed-code performance data without modifying application source code. According to the dotnet/skills repository, the dotnet-trace-collect skill implements standardized workflows for installing the tool, discovering target processes, and exporting traces in formats compatible with modern analysis tools.

Installing dotnet-trace

The tool supports two installation methods depending on your environment constraints.

Via .NET SDK (Recommended):

dotnet tool install -g dotnet-trace

Standalone Binary (No SDK Required):

When the .NET SDK is unavailable, download the pre-built binary directly from the official aka.ms redirect. In plugins/dotnet-diag/skills/dotnet-trace-collect/references/dotnet-trace-collect.md, the skill specifies this fallback for containerized environments:

curl -JL https://aka.ms/dotnet-trace/linux-x64 -o dotnet-trace
chmod +x dotnet-trace

Discovering Target Processes

Before collecting traces, identify running .NET processes using the built-in process list command:

dotnet-trace ps

This outputs process IDs (PIDs) and corresponding command lines, which you pass to the collection commands via the -p parameter.

Collecting Performance Traces

The dotnet-trace collect command supports multiple configuration strategies for different diagnostic scenarios.

Using Predefined Profiles

Profiles bundle common EventSource providers into convenient presets. According to the reference documentation in dotnet-trace-collect.md, available profiles include:

  • dotnet-sampled-thread-time: CPU sampling for thread time analysis
  • gc-verbose: Garbage collection start/stop events with detailed allocation data
dotnet-trace collect -p <PID> --profile gc-verbose -o /tmp/gc.nettrace

Custom Provider Configuration

For targeted diagnostics, specify individual providers as comma-separated values:

dotnet-trace collect -p <PID> \
  --providers System.Net.Http,System.Net.NameResolution,System.Net.Security,System.Net.Sockets \
  -o /tmp/network.nettrace

Common provider names include Microsoft-Windows-DotNETRuntime for runtime events and System.Net.Http for network I/O tracking.

Time-Limited Collection

Prevent unbounded trace files by setting explicit durations using the --duration flag:

dotnet-trace collect -p <PID> --duration 00:00:30 -o /tmp/short.nettrace

This stops collection automatically after 30 seconds.

Exporting to speedscope Format

For web-based flame graph visualization, export directly to JSON format compatible with speedscope:

dotnet-trace collect -p <PID> --format speedscope -o /tmp/trace.json

This bypasses the default .nettrace binary format and generates immediately viewable output.

Advanced Linux-Only Tracing with collect-linux

For .NET 10+ on Linux, the dotnet-trace collect-linux variant provides kernel-level event capture unavailable to standard collection. As documented in plugins/dotnet-diag/skills/dotnet-trace-collect/references/dotnet-trace-collect-linux.md, this mode utilizes the perf_events subsystem to capture native stacks and kernel events.

Requirements:

  • Root privileges (required for perf_events access)
  • .NET 10 or later runtime
  • Linux host environment
sudo dotnet-trace collect-linux -p <PID> --profile thread-time -o /tmp/linux.nettrace

This approach captures native frames from P/Invoke calls and interop layers that standard managed-code collection misses.

Analyzing Trace Output

After collection, analyze .nettrace files using the built-in reporting tool:

dotnet-trace report /tmp/trace.nettrace

This displays summary statistics including event counts, CPU usage distributions, and GC pause durations. For graphical analysis, open .nettrace files in PerfView or Visual Studio, or upload speedscope JSON exports to compatible web viewers.

Summary

Frequently Asked Questions

How do I collect traces from a .NET application running in a container without the SDK installed?

Download the standalone dotnet-trace binary using the aka.ms redirect URL for your container's architecture. As specified in the dotnet-trace-collect skill reference, you can curl the binary directly, make it executable, and run collection commands without installing the full .NET SDK.

What is the difference between dotnet-trace collect and dotnet-trace collect-linux?

The standard collect command captures managed-code events using EventSource providers and works across Windows, macOS, and Linux. The collect-linux variant, available only for .NET 10+ on Linux, leverages the kernel's perf_events subsystem to capture native stack frames and kernel events, but requires root privileges to access these low-level metrics.

Can I limit how long a trace runs to prevent generating huge files?

Yes. Use the --duration parameter with a timespan format (HH:MM:SS) to automatically stop collection after the specified interval. For example, --duration 00:01:00 captures exactly 60 seconds of data before terminating the session.

How do I analyze network performance specifically using dotnet-trace?

Specify the network-related EventSource providers using the --providers flag. Include System.Net.Http,System.Net.NameResolution,System.Net.Security,System.Net.Sockets to capture DNS resolution, TLS handshake, and socket I/O events. Collect the trace and then use dotnet-trace report to analyze latency and throughput patterns.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →