---
title: .NET performance metrics
source: https://docs.newrelic.com/docs/apm/agents/net-agent/other-features/net-performance-metrics
---

New Relic's .NET agent collects metrics from the .NET runtime about the performance of your application. These metrics can provide insight into how much CPU and memory an application consumes as well as how the performance of an application may be impacted by garbage collection and thread pool resource contention.

You can see these metrics at **[one.newrelic.com > All capabilities](https://one.newrelic.com/all-capabilities) > APM & services**. Select an application and go to **More views > Dotnet VMs**.

You can also view these metrics by:

-   Creating a custom [dashboard](https://docs.newrelic.com/docs/query-your-data/explore-query-data/dashboards/introduction-new-relic-one-dashboards).
-   Using the **Metric explorer** in **[one.newrelic.com > All capabilities](https://one.newrelic.com/all-capabilities) > APM & services** > select an application, and go to **More views**.

## CPU metrics [#cpu-metrics]

The following CPU metrics are collected:

| `CPU/User/Utilization` | The percentage of CPU that is consumed by this process.              |
| ---------------------- | -------------------------------------------------------------------- |
| `CPU/User Time`        | The amount of time the process has spent executing application code. |

## Memory metrics [#memory-metrics]

The following memory metrics are collected:

| `Memory/Physical`   | The amount of private (physical) memory, in MB, allocated to the process. |
| ------------------- | ------------------------------------------------------------------------- |
| `Memory/WorkingSet` | Amount of physical memory allocated to the process.                       |

## Garbage collection metrics [#garbage-collection]

The .NET garbage collector runs in the background and is responsible for identifying and reclaiming memory tied to objects that are no longer referenced by an application. The following metrics may be useful in identifying patterns of object allocation and potential over-allocation scenarios. This [article](https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals) further explains the fundamentals of garbage collection in .NET.

> #### ⚠️ IMPORTANT
>
> For .NET Framework applications, the Windows User under which your application runs must have access to windows performance counter data. Usually this is accomplished by adding the user to **Performance Monitor Users** and **Performance Log Users** groups. Insufficient permissions will result in the agent not collecting garbage collection metrics.

### Overall metrics [#overall-metrics]

Additionally, the following garbage collection metrics are collected:

| `GC/Handles`                               | The number of references to objects.                                                                                                                                                                                       |
| ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GC/Induced`                               | Normally, the runtime performs garbage collection automatically. This metric identifies the number of times that Garbage Collection was manually invoked by an explicit call to `GC.Collect` from within application code. |
| `GC/PercentTimeInGC` (.NET Framework only) | The percentage of elapsed time that the .NET runtime has spent performing garbage collection since the last garbage collection cycle.                                                                                      |

### Generation - 0 heap [#gen-0-heap]

The following garbage collection Gen0 metrics are collected:

| `GC/Gen0/Size`        | The amount of memory (in MB) that is _available_ to be allocated in Generation 0. This does not indicate the amount of memory that is being _used_ by Generation 0, but the maximum available to be allocated. |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GC/Gen0/Promoted`    | The amount of memory (in MB) that has survived garbage collection and has been promoted from Gen0 to Gen1. Memory survives garbage collection when there is an active reference to it.                         |
| `GC/Gen0/Collections` | The number of times Generation 0 Garbage Collection was executed by the garbage collector.                                                                                                                     |

### Generation - 1 heap [#gen-1-heap]

The following garbage collection Gen1 metrics are collected:

| `GC/Gen1/Size`        | The amount of memory (in MB) that is _used_ in the Generation 1 heap. This differs from `Gen0/Size` which measure the maximum amount of memory _available_ for the generation 0 heap.  |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GC/Gen1/Promoted`    | The amount of memory (in MB) that has survived garbage collection and has been promoted from Gen1 to Gen2. Memory survives garbage collection when there is an active reference to it. |
| `GC/Gen1/Collections` | The number of times Generation 1 Garbage Collection was executed by the garbage collector.                                                                                             |

### Generation - 2 heap [#gen-2-heap]

The following garbage collection Gen2 metrics are collected:

| `GC/Gen2/Size`                      | The amount of memory (in MB) that is being _used_ by the Gen2 Heap.                                                                                                                                                             |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GC/Gen2/Survived` (.NET Core Only) | The amount of memory (in MB) that has survived garbage collection. Memory survives garbage collection when there is an active reference to it. Unlike Gen0 and Gen1, memory that survives garbage collection is _not_ promoted. |
| `GC/Gen2/Collections`               | The number of times Generation 2 Garbage Collection was executed by the garbage collector.                                                                                                                                      |

### Large object heap (LOH) [#large-object-heap]

The following garbage collection LOH metrics are collected:

| `GC/LOH/Size`                      | The amount of memory (in MB) that is being _used_ by the Large Object Heap (LOH). In .NET Core, the Large Object Heap is sometimes referred to as Gen3.                                                                         |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GC/LOH/Survived` (.NET Core Only) | The amount of memory (in MB) that has survived garbage collection. Memory survives garbage collection when there is an active reference to it. Unlike Gen0 and Gen1, memory that survives garbage collection is _not_ promoted. |

## Managed thread pool metrics [#managed-thread-pool]

The .NET runtime manages a pool of threads. The following metrics provide visibility into the performance of an application in terms of the thread pool and may help identify areas of thread pool starvation. Thread pool starvation/contention occurs when there are not enough threads available to process the requests made by an application. The following [article](https://docs.microsoft.com/en-us/dotnet/standard/threading/the-managed-thread-pool) describes the various features of the managed thread pool. Please note that these metrics do _not_ include information about threads that are not managed by the thread pool.

### Worker threads [#worker-threads]

Worker threads are CPU-bound threads that are employed to perform work on behalf of a process.

| `Threadpool/Worker/Available` | Identifies the number of managed threads available to the process. Consistently low numbers indicate a potential starvation scenario. |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `Threadpool/Worker/InUse`     | Identifies the number of worker threads that are currently in use by the process.                                                     |

### Completion threads [#completion-threads]

Completion threads, sometimes referred to as I/O threads, are employed to monitor the completion of I/O operations.

| `Threadpool/Completion/Available` | This metric identifies the number of threads that are currently available to the process. Consistently low numbers indicate a potential starvation scenario. |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Threadpool/Completion/InUse`     | This metric identifies the number of completion threads currently in use by the process.                                                                     |

### Throughput [#throughput]

Throughput metrics measure how much work has been requested to be performed on a different thread, the amount of work that has been started, and how much work is waiting for a thread pool resource to become available.

| `Threadpool/Throughput/Requested`   | Identifies the number of times that work has been requested to be run on a different thread pool managed thread.                                                                                                                                                                                                                                                                     |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Threadpool/Throughput/Started`     | Identifies the number of work items requested to be run on a separate thread that have started execution.                                                                                                                                                                                                                                                                            |
| `Threadpool/Throughput/QueueLength` | Identifies the number of work items that have been requested, but are waiting to start. Numbers that consistently increase indicate a potential thread pool starvation situation. The following [article](https://docs.microsoft.com/en-us/dotnet/api/system.threading.threadpool.setmaxthreads) describes how to modify the number of threads that are available to an application. |
