Skip to content

[Pre6] Better EP docs with new names #35577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ In the app's project file (`.csproj`):
<WasmProfilers>browser;</WasmProfilers>
<WasmNativeStrip>false</WasmNativeStrip>
<WasmNativeDebugSymbols>true</WasmNativeDebugSymbols>
<!-- disable debugger -->
<WasmDebugLevel>0</WasmDebugLevel>
</PropertyGroup>
```

Expand Down
156 changes: 94 additions & 62 deletions aspnetcore/blazor/performance/webassembly-event-pipe-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Learn about Event Pipe diagnostics and how to get a Garbage Collect
monikerRange: '>= aspnetcore-10.0'
ms.author: wpickett
ms.custom: mvc
ms.date: 05/02/2025
ms.date: 06/04/2025
uid: blazor/performance/webassembly-event-pipe
---
# ASP.NET Core Blazor WebAssembly Event Pipe diagnostics
Expand All @@ -16,116 +16,148 @@ uid: blazor/performance/webassembly-event-pipe

-->

This article describes Event Pipe diagnostic tools, counters, and how to get a Garbage Collector heap dump in Blazor WebAssembly apps.
This article describes diagnostic tools and how to use them in Blazor WebAssembly apps.

## Prerequisite
## Prerequisite for all scenarios

Install the [.NET WebAssembly build tools](xref:blazor/tooling/webassembly#net-webassembly-build-tools):

```dotnetcli
dotnet workload install wasm-tools
```

## .NET Core Diagnostics Client Library example
## How a WebAssembly app uses memory and how to troubleshoot memory leaks

Parse and validate NetTrace (`.nettrace`) messages using the .NET Core Diagnostics Client Library:
In the app's project file (`.csproj`), add following properties for the duration of the investigation:

* [`dotnet/diagnostics` GitHub repository](https://github.com/dotnet/diagnostics)
* [`Microsoft.Diagnostics.NETCore.Client` NuGet package](https://www.nuget.org/packages/Microsoft.Diagnostics.NETCore.Client)
```xml
<!-- do not enable diagnostics in production, as it has a negative performance impact -->
<PropertyGroup>
<EnableDiagnostics>true</EnableDiagnostics>
</PropertyGroup>
```

For more information, see the [.NET Core diagnostics documentation](/dotnet/core/diagnostics/) and the [`IpcMessage` API (reference source)](https://github.com/dotnet/diagnostics/blob/main/src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcMessage.cs).
> [!WARNING]
> Don't enable diagnostics in production because it has a negative performance impact.

[!INCLUDE[](~/includes/aspnetcore-repo-ref-source-links.md)]
Build your app with the `wasm-tools` workload.

The MSBuild properties in the following table enable profiler integration.
Open the app in a browser and navigate to problematic pages or components.

Property | Default | Set value to&hellip; | Description
--- | :---: | :---: | ---
`<WasmPerfTracing>` | `false` | `true` | Enables support for WebAssembly performance tracing.
`<WasmPerfInstrumentation>` | No value | See table&dagger; | Enables instrumentation necessary for the sampling profiler. The property follows the :::no-loc text="callspec"::: syntax. &dagger;For permissible values, see the following table.
`<MetricsSupport>` | `false` | `true` | Enables `System.Diagnostics.Metrics` support. For more information, see the [`System.Diagnostics.Metrics` namespace](/dotnet/api/system.diagnostics.metrics).
`<EventSourceSupport>` | `false`| `true` | Enables `EventPipe` support. For more information, see [Diagnostics and instrumentation: Observability and telemetry](/dotnet/core/deploying/native-aot/diagnostics#observability-and-telemetry).
Take a managed memory dump by calling `collectGcDump` JavaScript API:

The following table describes permissable `<WasmPerfInstrumentation>` values.
```javascript
globalThis.getDotnetRuntime(0).collectGcDump();
```

`<WasmPerfInstrumentation>` value | Description
--- | ---
`all` | All assemblies
`program` | Entry point assembly
`{ASSEMBLY}` | Specifies an assembly (`{ASSEMBLY}`)
`M:Type:{METHOD}` | Specifies a method (`{METHOD}`)
`N:{NAMESPACE}` | Specifies a namespace (`{NAMESPACE}`)
`T:{TYPE}` | Specifies a type (`{TYPE}`)
`+EXPR` | Includes expression
`-EXPR` | Excludes expression
Call the preceding API from either a browser devoloper tools console or JavaScript code of the app.

A `.nettrace` file is downloaded from the browser into a local folder.

Convert the dump to `.gcdump` format using the `dotnet-gcdump` tool. To view the converted `.gcdump` file, use Visual Studio or PrefView.

For more information, see [View the GC dump captured from dotnet-gcdump](/dotnet/core/diagnostics/dotnet-gcdump#view-the-gc-dump-captured-from-dotnet-gcdump).

Enabling profilers has negative size and performance impacts, so don't publish an app for production with profilers enabled. In the following example, a condition is set on a property group section that only enables profiling when the app is built with `/p:BlazorSampleProfilingEnabled=true` (.NET CLI) or `<BlazorSampleProfilingEnabled>true</BlazorSampleProfilingEnabled>` in a Visual Studio publish profile, where "`BlazorSampleProfilingEnabled`" is a custom symbol name that you choose and doesn't conflict with other symbol names.
## How a WebAssembly app uses CPU and how to find slow or hot methods

In the app's project file (`.csproj`):
In the app's project file (`.csproj`), add following properties for the duration of the investigation:

```xml
<PropertyGroup Condition="'$(BlazorSampleProfilingEnabled)' == 'true'">
<WasmPerfTracing>true</WasmPerfTracing>
<MetricsSupport>true</MetricsSupport>
<EventSourceSupport>true</EventSourceSupport>
<!-- do not enable diagnostics in production, as it has a negative performance impact -->
<PropertyGroup>
<EnableDiagnostics>true</EnableDiagnostics>
<!-- disable debugger -->
<WasmDebugLevel>0</WasmDebugLevel>
<!-- sampling in all methods, see below for filtering options -->
<WasmPerformanceInstrumentation>all</WasmPerformanceInstrumentation>
</PropertyGroup>
```

Alternatively, enable features when the app is built with the .NET CLI. The following options passed to the `dotnet build` command mirror the preceding MS Build property configuration:
> [!WARNING]
> Don't enable diagnostics in production because it has a negative performance impact.

```dotnetcli
/p:WasmPerfTracing=true /p:WasmPerfInstrumentation=all /p:MetricsSupport=true /p:EventSourceSupport=true
Build the app with the `wasm-tools` workload.

Open the app in a browser and navigate to problematic pages or components.

Start colllecting CPU samples for 60 seconds by calling the `collectCpuSamples` JavaScript API:

```javascript
globalThis.getDotnetRuntime(0).collectCpuSamples({durationSeconds: 60});
```

The [`Timing-Allow-Origin` HTTP header](https://developer.mozilla.org/docs/Web/HTTP/Reference/Headers/Timing-Allow-Origin) allows for more precise time measurements.
Call the preceding API from either a browser devoloper tools console or JavaScript code of the app.

## EventPipe profiler
Start using the app to run problematic code.

[EventPipe](/dotnet/core/diagnostics/eventpipe) is a runtime component used to collect tracing data, similar to [ETW](/windows/win32/etw/event-tracing-portal) and [perf_events](https://wikipedia.org/wiki/Perf_%28Linux%29).
After the predefined period, the browser downloads a `.nettrace` file into a local folder. To view the `.nettrace` file, use Visual Studio or PrefView.

Use the `<WasmPerfInstrumentation>` property to enable CPU sampling instrumentation for diagnostic server. This setting isn't necessary for memory dump or counters. **Makes the app execute slower. Only enable this for performance profiling.**
For more information, see [Use EventPipe to trace your .NET application](/dotnet/core/diagnostics/eventpipe#use-eventpipe-to-trace-your-net-application).

Enabling profilers has negative size and performance impact, so don't publish an app for production with profilers enabled. In the following example, a condition is set on a property group section that only enables profiling when the app is built with `/p:BlazorSampleProfilingEnabled=true` (.NET CLI) or `<BlazorSampleProfilingEnabled>true</BlazorSampleProfilingEnabled>` in a Visual Studio publish profile, where "`BlazorSampleProfilingEnabled`" is a custom symbol name that you choose and doesn't conflict with other symbol names.
The [`Timing-Allow-Origin` HTTP header](https://developer.mozilla.org/docs/Web/HTTP/Reference/Headers/Timing-Allow-Origin) allows for more precise time measurements.

```xml
<PropertyGroup Condition="'$(BlazorSampleProfilingEnabled)' == 'true'">
<WasmPerfInstrumentation>all</WasmPerfInstrumentation>
</PropertyGroup>
```
## How to observe metrics emmited by a WebAssembly app

Collect CPU counters for 60 seconds with `collectCpuSamples(durationSeconds)`:
In the app's project file (`.csproj`), add following properties for the duration of the investigation:

```javascript
globalThis.getDotnetRuntime(0).collectCpuSamples({durationSeconds: 60});
```xml
<!-- do not enable diagnostics in production, as it has a negative performance impact -->
<PropertyGroup>
<EnableDiagnostics>true</EnableDiagnostics>
<MetricsSupport>true</MetricsSupport>
<EventSourceSupport>true</EventSourceSupport>
</PropertyGroup>
```

To view the trace, see [Use EventPipe to trace your .NET application](/dotnet/core/diagnostics/eventpipe#use-eventpipe-to-trace-your-net-application).
> [!WARNING]
> Don't enable diagnostics in production because it has a negative performance impact.

## GC (Garbage Collector) dumps
Build the app with the `wasm-tools` workload.

The [`dotnet-gcdump` (`collect`/convert` options)](/dotnet/core/diagnostics/dotnet-gcdump) global tool collects GC (Garbage Collector) dumps of live .NET processes using [EventPipe](/dotnet/core/diagnostics/eventpipe).
Open the app in a browser and navigate to problematic pages or components.

Collect a GC (Garbage Collector) dump of the live .NET process with `collectGcDump`:
Start colllecting metrics for 60 seconds by calling the `collectMetrics` JavaScript API:

```javascript
globalThis.getDotnetRuntime(0).collectGcDump();
globalThis.getDotnetRuntime(0).collectMetrics({durationSeconds: 60});
```

To view the captured GC dump, see [View the GC dump captured from dotnet-gcdump](/dotnet/core/diagnostics/dotnet-gcdump#view-the-gc-dump-captured-from-dotnet-gcdump).
Call the preceding API from either a browser devoloper tools console or JavaScript code of the app.

## Counters trace
After the predefined period, the browser downloads a `.nettrace` file into a local folder. To view the `.nettrace` file, use Visual Studio or PrefView.

[`dotnet-counters collect`](/dotnet/core/diagnostics/dotnet-counters) is a performance monitoring tool for ad-hoc health monitoring and first-level performance investigation.
For more information, see [Use EventPipe to trace your .NET application](/dotnet/core/diagnostics/eventpipe#use-eventpipe-to-trace-your-net-application).

Collect diagnostic counters for 60 seconds with `collectPerfCounters(durationSeconds)`:
## MSBuild properties that enable diagnostic integration

```javascript
globalThis.getDotnetRuntime(0).collectPerfCounters({durationSeconds: 60});
```
Property | Default | Set value to&hellip; | Description
--- | :---: | :---: | ---
`<EnableDiagnostics>` | `false` | `true` | Enables support for WebAssembly performance tracing.
`<WasmPerformanceInstrumentation>` | No value | See table&dagger; | Enables instrumentation necessary for the sampling profiler. The property follows the :::no-loc text="callspec"::: syntax. &dagger;For permissible values, see the following table.
`<MetricsSupport>` | `false` | `true` | Enables `System.Diagnostics.Metrics` support. For more information, see the [`System.Diagnostics.Metrics` namespace](/dotnet/api/system.diagnostics.metrics).
`<EventSourceSupport>` | `false`| `true` | Enables `EventPipe` support. For more information, see [Diagnostics and instrumentation: Observability and telemetry](/dotnet/core/deploying/native-aot/diagnostics#observability-and-telemetry).

The following table describes permissable `<WasmPerformanceInstrumentation>` values.

`<WasmPerformanceInstrumentation>` value | Description
--- | ---
`all` | All assemblies
`program` | Entry point assembly
`{ASSEMBLY}` | Specifies an assembly (`{ASSEMBLY}`)
`M:Type:{METHOD}` | Specifies a method (`{METHOD}`)
`N:{NAMESPACE}` | Specifies a namespace (`{NAMESPACE}`)
`T:{TYPE}` | Specifies a type (`{TYPE}`)
`+EXPR` | Includes expression
`-EXPR` | Excludes expression

Your code should yield to main browser loop often to allow the trace to be collected. When executing long running loops, the internal diagnostic buffers could overflow.

To view the trace, see [Use EventPipe to trace your .NET application](/dotnet/core/diagnostics/eventpipe#use-eventpipe-to-trace-your-net-application).
**Enabling profilers and diagnostic tools has negative size and performance impacts, so don't publish an app for production with profilers enabled.**

## Additional resources

* [EventPipe](/dotnet/core/diagnostics/eventpipe) is a runtime component used to collect tracing data, similar to [ETW](/windows/win32/etw/event-tracing-portal) and [perf_events](https://wikipedia.org/wiki/Perf_%28Linux%29).
* [What diagnostic tools are available in .NET Core?](/dotnet/core/diagnostics/)
* [.NET diagnostic tools](/dotnet/core/diagnostics/tools-overview)
* [`dotnet/diagnostics` GitHub repository](https://github.com/dotnet/diagnostics)
* [`Microsoft.Diagnostics.NETCore.Client` NuGet package](https://www.nuget.org/packages/Microsoft.Diagnostics.NETCore.Client)