Unreal Engine ships with some powerful features for profiling CPU, GPU, and memory performance. In Unreal Engine 5, they’re delivered by Unreal Insights, a suite of tools for capturing performance data at runtime and analysing it. It takes the place of the older Unreal Profiler available in UE 4 and deprecated in 5.0.
In this post, I’ll walk through the basics of profiling via Unreal Insights (with an emphasis on measuring the CPU performance of custom C++ code) as well as how to set up two third-party C++ profilers - Tracy and Optick.
Everything I demonstrate in this post is based on Unreal Engine 5.4.4, but should apply to any 5.*
version. Also note that I won’t go into detail with respect to profiler result analysis and code optimisation as these are both deep topics that warrant posts of their own. Regardless, I hope you find this useful!
Unreal Insights
Unreal Insights consists of two executables:
- UnrealTraceServer: the backend. The server is responsible for recording high volumes of performance data (categorised by Channels) from the engine.
- UnrealInsights: the frontend. This includes the Session Browser GUI for opening and analysing traces stored by the trace server.
Before you begin tracing, you can select the trace channels you’re interested in via the Trace menu in the bottom right of the editor:
Note that the defaults are sufficient for common profiling tasks.
Starting a trace session
There are two ways of starting a trace session:
- Via the Trace menu, which allows you to profile your game while it’s running in the editor viewport.
- By starting your game in standalone mode with the Session Browser window open.
The latter method is preferable since it means your game is running independently of the editor, eliminating some of the overhead associated with running it inside the editor and giving you a more accurate picture of performance - not to mention it does away with the need to manually start and stop traces.
To do this, first make sure your play mode is set to Standalone Game:
Then open up the Session Browser window via the Trace menu:
As long as you keep that window open, the editor should automatically start tracing every time you start the game. Closing the game window will similarly terminate the trace session.
The trace server should automatically start when you launch Unreal Editor. If it’s not running, traces will fail to start.
If attempting to start the server via the Trace menu doesn’t work (which was the case for me when I last tried this on a new UE 5.5 project), you can start it manually. On Windows, you can find the binary at Engine\Binaries\Win64\UnrealTraceServer.exe
under your Unreal Engine installation directory. You can start it as a background process by executing UnrealTraceServer.exe fork
.
The command may result in the error “Error: Deamon is configured to run in sponsored mode, but no sponsor pid has been specified.”. When the server runs in sponsor mode, it’ll only run as long as any local processes are using it, then it’ll shut down. You can disable sponsored mode by modifying the settings.ini
file specified in the output (by default, this should be C:\Users\<user>\AppData\Local\UnrealEngine\Common\UnrealTrace\settings.ini
) to specify Sponsored=0
. The server should then start successfully with UnrealTraceServer.exe fork
.
When you’re done using the trace server, you can kill it with UnrealTraceServer.exe kill
.
The Trace Store tab in the Session Browser lists all of the traces stored on the server, including live ones (denoted with “LIVE” in the status column). Double-clicking a trace will open it, presenting you with a frame time graph, a flame graph of timer events, a table of timers and their performance stats, and a few other views:
Timing custom C++ code
The engine provides a range of macros for instrumenting your code with trace events. There are different types of event covering CPU timing, counters, memory allocations and more, and it’s possible to define custom event types so you can implement more specialised tracing behaviour depending on your exact needs.
For this example, I’ll use one of the built-in scoped timer macros defined in Source/Runtime/Core/Public/ProfilingDebugging/CpuProfilerTrace.h, TRACE_CPUPROFILER_EVENT_SCOPE_STR
. This timer starts measuring at the point the macro is called and automatically stops measuring via the RAII mechanism in C++. Its usage looks like this:
To demonstrate this, I’ll create some artificial spikes in frame time in one of my projects, which has an enemy actor type that seeks and attacks the player. I’ll insert a sleep duration of 30ms in its InflictWeaponDamageOnTarget
method and time it like so:
Obviously this isn’t a realistic example of an expensive workload, but it serves the purpose of making frames stand out in the trace results.
After around 25s of gameplay, here are the results:
This type of timer is one of the most commonly used features of C++ profilers, which all have similar macros.
Alternative profilers
Unreal Engine exposes FExternalProfiler
, an interface for external profiler integration. See Engine/Source/Runtime/Core/Public/ProfilingDebugging/ExternalProfiler.h.
I’ll possibly write a guide for integrating profilers with this API at a later date. For now, I’ll cover setting up Tracy and Optick with existing integrations.
Tracy
Nesquick0/TracyUnrealPlugin provides a solid starting point for a plugin that provides a Tracy implementation. At the time of writing, it’s compatible with Tracy 0.9.1 (with some modifications) and current versions of Unreal Engine 5. Installation is detailed in the readme, but in short:
- Copy the
Tracy
directory from the repo into thePlugins
subdirectory of your project (create the subdirectory if it doesn’t already exist) - From a copy of Tracy 0.9.1 source (downloadable here), copy the
public
directory toPlugins\Tracy\Source\TracyLib
- Modify
Plugins\Tracy\Source\TracyLib\public\client\TracyProfiler.cpp
as follows:
In addition to modifying TracyProfiler.cpp, you’ll also need to modify the plugin’s FExternalProfiler
implementation to make it compatible:
Plugins\Tracy\Source\Tracy\Public\TracyPlugin.h
:
Plugins\Tracy\Source\Tracy\Private\TracyPlugin.cpp
:
At this point, Tracy.exe should be able to connect to the editor or your game as long as they’re launched with the -tracy
command line argument. To set this argument for the game in Standalone Game mode, edit the advanced play mode settings and add -tracy
to the “Additional Launch Parameters” setting:
Optick
Optick’s author maintains an Unreal Engine plugin for Optick support. It’s available on Fab. At the time of writing, the latest engine version it supports is 5.0.
After adding the plugin to your library, you can find it in the Epic Games Launcher under Library > Fab Library and install it to a compatible engine installation.
With the plugin installed, enable it in the editor by going to Edit > Plugins > Installed > Performance, enabling the plugin, and restarting the editor. You can then open Optick via Tools > Open Optick Profiler.
As noted in the plugin documentation, Optick uses Event Tracing for Windows (ETW) to capture kernel-level events. If you need to do that, you’ll need to launch the editor (or your game) with administrator privileges.
Closing remarks
While profilers give you the means to dissect frames and really understand what’s happening, it’s worth noting that the editor also exposes stat commands, which in most cases should be checked as a first resort as they can give you immediate insight into potential issues. The most useful of these is arguably stat unit
, which displays a selection of real-time stats including frame time, draw call count, and the number of primitives being drawn. stat fps
is similarly useful for observing framerate performance. You can execute these in the console (opened with the `
(tilde) key) when running your game via the editor.
You can find a full list of stat commands in the documentation.
That being said, profilers are powerful tools that, when used effectively, can help you avoid wasting time on red herrings. If you have performance issues and you’re unsure of the root cause based on some superficial investigation, you should definitely take advantage of a profiler. I hope this post has been useful to that end!