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

> Collect and analyze .NET performance traces with dotnet-trace. Capture CPU, GC, and allocation events easily. Explore results with dotnet-trace report or speedscope exports.

- Repository: [.NET Platform/skills](https://github.com/dotnet/skills)
- Tags: how-to-guide
- Published: 2026-07-07

---

**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):**

```bash
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`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-diag/skills/dotnet-trace-collect/references/dotnet-trace-collect.md), the skill specifies this fallback for containerized environments:

```bash
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:

```bash
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`](https://github.com/dotnet/skills/blob/main/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

```bash
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:

```bash
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:

```bash
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:

```bash
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`](https://github.com/dotnet/skills/blob/main/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

```bash
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:

```bash
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

- **Installation**: Use `dotnet tool install -g dotnet-trace` when SDK is available; otherwise download platform-specific binaries from `aka.ms` redirects.
- **Process Discovery**: Run `dotnet-trace ps` to identify target PIDs before collection.
- **Collection Modes**: Standard `collect` works across all platforms for managed code; `collect-linux` requires root but captures native stacks via `perf_events` on Linux with .NET 10+.
- **Output Formats**: Default `.nettrace` files work with PerfView and Visual Studio; use `--format speedscope` for web-based flame graphs.
- **Reference Sources**: Implementation details reside in [`plugins/dotnet-diag/skills/dotnet-trace-collect/references/dotnet-trace-collect.md`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-diag/skills/dotnet-trace-collect/references/dotnet-trace-collect.md) and [`dotnet-trace-collect-linux.md`](https://github.com/dotnet/skills/blob/main/dotnet-trace-collect-linux.md), with evaluation logic in [`tests/dotnet-diag/dotnet-trace-collect/eval.yaml`](https://github.com/dotnet/skills/blob/main/tests/dotnet-diag/dotnet-trace-collect/eval.yaml).

## 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.