Search Unity

Customizing performance metrics in the Unity Profiler

April 29, 2022 in Technology | 13 min. read
Unity Profiler custom metrics
Unity Profiler custom metrics

Optimizing your application requires being able to accurately measure how your project consumes hardware resources. Extending the Unity Profiler with your own performance metrics enables you to better understand your application’s unique performance story. In this post, we will cover new Profiler extensibility features in Unity 2021 LTS.

Our new Profiler counters provide a lightweight mechanism for adding your own performance metrics to your Unity applications and packages. You can also now visualize your metrics directly in the Profiler window by adding your own Profiler Modules. Read on for more details on how to use these features to improve the performance of your Unity project.

What is the Unity Profiler?

The Unity Profiler is a tool you can use to get detailed performance information about your application. It tracks a large number of performance metrics across a range of categories, such as memory, audio, and rendering. These metrics are visualized in the Profiler window, and in some cases they may also be queried from script. Using this information, you can gain insights into how your Unity application uses the available hardware resources of the target platform, which can help you pinpoint where optimizations might be made.

Overview of the Unity profiler

Profiler counters

What are Profiler counters?

Profiler counters track, measure, or count metrics in your Unity application that are useful for performance analysis purposes. For example, Unity defines a built-in Profiler counter to track the total number of bytes of memory used by your application, called “Total Used Memory”. This is a useful statistic to gauge your app’s memory footprint on the target device. You can see this value displayed over time alongside other memory-related metrics in the Profiler window’s Memory module, shown below.

An overview of the Profiler's memory module

Custom Profiler counters

By adding your own Profiler counters, you can expose performance metrics unique to your own systems and applications. These metrics can be displayed in the Profiler window alongside other performance data, including built-in counters. This enables you to view the performance characteristics unique to your application, in context, directly in the Profiler window.

In the example below, a custom Profiler counter has been added to track the number of active creatures in a scene. It is shown alongside the built-in Profiler counter, Batches Count, which tracks the number of rendering batches processed each frame. This allows us to easily correlate between the two metrics and see the impact of our creature count on the number of batches the renderer must process.

A custom Profiler counter shown alongside the built-in Profiler counter, Batches Count, which tracks the number of rendering batches processed each frame
See bottom left corner for an example of Profiler counters in a game UI.

Additionally, all of your Profiler counters are available in Release Builds, as well as some of the built-in ones where specified. Release Builds are more representative of the real-world performance of your application than Development Builds. 

However, the Unity Profiler cannot be attached to Release Builds for optimization reasons. Therefore, you can selectively monitor important metrics in Release Builds by using Profiler counters and querying them from script. For example, you might do this in Continuous Integration testing to detect performance regressions. Or, you might display some key performance metrics via an in-game debug user interface using one of Unity’s UI systems, such as in the lower-left corner of the example below. Please see the Profiler Recorder documentation for more information.

An example of Profile counter in a game UI
See bottom left corner for an example of Profiler counters in a game UI.

If you want your Profiler counters to be present only in Development Builds, you can exclude them from Release Builds by wrapping them in the DEVELOPMENT_BUILD scripting symbol, as described in the Conditional Compilation documentation.

Getting started

Our Profiler counters are available in the Profiling.Core package, released in Unity 2021 LTS. The package is bundled with Unity 2021 LTS but not installed by default, so please follow the installation instructions in the package documentation to add this package from the Package Manager by name.

Once you have the package, you can create a Profiler counter, referred to in the API as a ProfilerCounter or ProfilerCounterValue, and update it as follows.

using UnityEngine;
using Unity.Profiling;

public class CreatureCounter : MonoBehaviour
{
    static readonly ProfilerCounterValue<int> k_CreatureCounter = new(
        ProfilerCategory.Scripts,
        "Creature Count",
        ProfilerMarkerDataUnit.Count,
        ProfilerCounterOptions.FlushOnEndOfFrame);

    void OnEnable()
    {
        k_CreatureCounter.Value += 1;
    }

    void OnDisable()
    {
        k_CreatureCounter.Value -= 1;
    }
}

Please see the Profiling.Core package documentation for more information.

Profiler modules

What is a Profiler module?

A Profiler module presents performance information for a specific area or workflow in the Profiler window, such as memory, audio, or rendering. Each Profiler module aims to provide insight into the performance profile of its domain. For example, the Memory Profiler module shown below displays seven key metrics relating to memory usage over time. Below that is the module’s detailed section showing the distribution of memory in the selected frame.

A module sowing the distribution of memory in the selected frame

Custom Profiler modules

In Unity 2021 LTS, the Profiler window can be customized with your own Profiler modules. This enables you to present the performance metrics of your own systems directly in the Profiler window. It also provides the opportunity for custom visualization in your module’s detailed view, allowing you to present your system’s performance data however you wish.

Profiler Module Editor

The Profiler Module Editor is recommended for quickly creating temporary Profiler modules for your own use. For example, you might use it to quickly create a Profiler module to verify a new Profiler counter. Profiler modules created via the Profiler Module Editor are local to your Editor and are not available for other project users.

Profiler Module Editor

For more information, please see the Module Editor documentation.

Profiler module API

The Profiler module API allows you to add your own Profiler module to the Profiler window for all users of a project or package. When a Profiler module is defined in a project or package using this API, it automatically becomes available in the Profiler window for all users of that project or package.

If you are an Asset Store publisher or a package developer, you can now distribute custom Profiler modules with your package. When a user installs your package, your Profiler modules will automatically become available in the Profiler window for your users. This enables you to expose your package’s performance metrics directly in the Profiler window.

Several teams within Unity have already been using this API to distribute custom Profiler modules with their packages, including the Netcode for GameObjects, Adaptive Performance, and Mali System Metrics packages.

How to use it

To add a Profiler module using the Profiler module API, create a ProfilerModule script in your project or package, as shown below.

using Unity.Profiling;
using Unity.Profiling.Editor;

[System.Serializable]
[ProfilerModuleMetadata("Creature Batches")]
public class CreatureBatchesProfilerModule : ProfilerModule
{
    static readonly ProfilerCounterDescriptor[] k_Counters =
    {
        new("Creature Count", ProfilerCategory.Scripts),
        new("Batches Count", ProfilerCategory.Render),
    };

    public CreatureBatchesProfilerModule() : base(k_Counters) { }
}

The module will be displayed automatically in the Profiler window for all users of the project or package.

Module in Profiler window

For more information on using the Profiler module API, please see the Manual and API documentation.

The Profiler module API includes the ability to draw a custom visualization of your performance data for the selected frame using one of Unity’s Editor UI systems, such as UI Toolkit

For example, the Adaptive Performance package’s Profiler module uses this API to present detailed performance information in the selected frame, as well as contextual information such as Bottleneck and Thermal Warning indicators. These indicators can help a user of the Adaptive Performance package to clearly see when they may be encountering thermal throttling, for example. You might use this API to present a bespoke visualization of your Profiler module’s performance data.

An API with bespoke visualization of a Profiler module's performance data

For more information, please see the Manual and API documentation on creating a custom Profiler Module Details view.

Additional contextual data

You may wish to visualize additional, more complex data in your Profiler modules alongside your Profiler counters. For example, you might wish to display a screen capture of the current frame in your Profiler module’s detailed view to give more context to the performance data, as shown below.

Profiler's module detailed view with performance data

To send additional frame data to the Profiler, such as an image, and subsequently retrieve it from the Profiler capture, you can use the Frame Metadata APIs, Profiler.EmitFrameMetaData and FrameDataView.GetFrameMetaData

If you have additional data that only needs to be sent once per profiling session, such as configuration data, you can use the Session Metadata APIs, Profiler.EmitSessionMetaData and FrameDataView.GetSessionMetaData.

Please see the documentation linked above for examples of how and when to use these features.

Conclusion

In this post, we covered how to extend the Unity Profiler with your own performance metrics. We looked at adding custom metrics with our new Profiler counters, available in the Profiling.Core package. Then, we explored adding custom Profiler modules to the Profiler window with both the Profiler Module Editor and the Profiler Module API. Finally, we covered sending additional complex data to the Profiler, such as an image, to provide more contextual information.

We hope these Profiler extensibility features added in Unity 2021 LTS enable you to better measure and understand your application’s unique performance story. Please feel free to reach out to the team via our forum page. We would love to hear your feedback and learn how we can improve Unity’s performance tooling for you.

April 29, 2022 in Technology | 13 min. read