Profile and optimize Unreal Engine performance — Unreal Insights (trace-based CPU/GPU/memory profiling, .utrace sessions, Timing Insights, Memory Insights), stat commands (stat unit/fps/game/gpu/scenerendering/memory and the full stat command table), stat groups, C++ instrumentation (DECLARE_STATS_GROUP, DECLARE_CYCLE_STAT, SCOPE_CYCLE_COUNTER, QUICK_SCOPE_CYCLE_COUNTER, TRACE_CPUPROFILER_EVENT_SCOPE, CSV_SCOPED_TIMING_STAT), memory profiling (LLM, MemReport, memreport -full), and the measurement-first optimization workflow. Use when diagnosing frame-rate drops, hitches, CPU/GPU bottlenecks, or memory growth, when adding timing instrumentation to find a hotspot, or when deciding on CPU vs GPU vs memory optimization levers.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Instruções da origem · Visualização somente leitura
name
profiling-and-optimization
description
Profile and optimize Unreal Engine performance — Unreal Insights (trace-based CPU/GPU/memory profiling, .utrace sessions, Timing Insights, Memory Insights), stat commands (stat unit/fps/game/gpu/scenerendering/memory and the full stat command table), stat groups, C++ instrumentation (DECLARE_STATS_GROUP, DECLARE_CYCLE_STAT, SCOPE_CYCLE_COUNTER, QUICK_SCOPE_CYCLE_COUNTER, TRACE_CPUPROFILER_EVENT_SCOPE, CSV_SCOPED_TIMING_STAT), memory profiling (LLM, MemReport, memreport -full), and the measurement-first optimization workflow. Use when diagnosing frame-rate drops, hitches, CPU/GPU bottlenecks, or memory growth, when adding timing instrumentation to find a hotspot, or when deciding on CPU vs GPU vs memory optimization levers.
metadata
{"engine-version":"5.8","category":"tooling"}
Profiling & optimization
Optimize by measurement, not guesswork: capture data, find the actual hotspot, fix it,
re-measure. The three tool layers are Unreal Insights (deep trace-based profiling),
the in-game stat commands (quick triage), and instrumentation macros for your own
code. Start with stat commands to identify which thread owns the frame budget, then open
Insights for a precise call-by-call view.
When to use this skill
Frame rate is low or hitching; determining whether the game thread, render thread, or
GPU is the bottleneck.
Adding per-system timing so it appears by name in Insights and stat output.
Memory growth, out-of-memory events, or finding which system owns an allocation.
Deciding which optimization lever to pull after identifying the hotspot.
Triage first: stat commands
In the console (PIE or standalone game):
Command
What it shows
stat unit
Frame / Game / Draw / GPU / RHIT split — the first command to run
stat fps
Raw frame rate
stat game
Game-thread breakdown by system
stat gpu
GPU pass costs (requires -trace=gpu or GPU channel)
The stat system shows named timers in stat <group> output and in Insights.
// In a .cpp (file scope — single translation unit):DECLARE_STATS_GROUP(TEXT("MySystem"), STATGROUP_MySystem, STATCAT_Advanced);
DECLARE_CYCLE_STAT(TEXT("MySystem Update"), STAT_MySystemUpdate, STATGROUP_MySystem);
// In the function:voidUMySystem::Update(){
SCOPE_CYCLE_COUNTER(STAT_MySystemUpdate);
// ... work ...
}
For a stat accessible across multiple files, declare with DECLARE_CYCLE_STAT_EXTERN in
the header and DEFINE_STAT in the .cpp.
QUICK_SCOPE_CYCLE_COUNTER is a one-liner for temporary instrumentation — it creates and
uses a cycle counter in STATGROUP_Quick with no prior declaration:
voidAMyActor::Tick(float DeltaTime){
QUICK_SCOPE_CYCLE_COUNTER(STAT_MyActor_Tick);
// ... work ...
}
Instrumentation — CPU profiler trace scopes
TRACE_CPUPROFILER_EVENT_SCOPE writes directly to the Trace system (cpu channel) and
is visible in the Timing Insights timeline. Lower overhead than the stat system; preferred
for high-frequency scopes.
#include"ProfilingDebugging/CpuProfilerTrace.h"voidAMySystem::Step(){
TRACE_CPUPROFILER_EVENT_SCOPE(AMySystem::Step);
// ... work ...
}
For a dynamic (runtime-determined) scope name use TRACE_CPUPROFILER_EVENT_SCOPE_TEXT:
Dumps a detailed memory breakdown to Saved/Profiling/MemReports/. Covers pool allocators,
UObject counts, asset memory, texture streaming, etc.
LLM (Low Level Memory Tracker)
LLM instruments every allocation with a tag. Enable with -llm on the command line; view
with stat llm, stat llmfull, or via Insights MemTag channel.
LLM tags are defined in LowLevelMemTracker.h
(Runtime/Core/Public/HAL/LowLevelMemTracker.h). Tags relevant to games: UObject,
RenderTargets, Shaders, Meshes, Audio, Animation.
Insights Memory Insights
Run with -trace=memalloc,memtag,callstack,module (Development build). Open Memory
Insights from the Menu inside a loaded trace. Use "Memory Leaks" query to find allocations
alive across a level transition, or "Growth" to find what grew between two moments.
ProfileGPU (console command) / GPU Visualizer (Editor menu) — one-frame GPU breakdown,
shows pass tree with ms costs.
Insights GPU track — timeline view of GPU passes alongside CPU work; requires
-trace=gpu.
Common GPU costs to investigate: shadow passes (stat shadowrendering), translucency
overdraw, post-process stack, screen percentage, too many dynamic lights.
Common optimization levers (after measuring)
Symptom
Lever
Game thread high, many ticks
Disable unnecessary ticking; use timers/events (timers-and-async)
Reduce translucency layers, cull small objects, lower screen percentage
GC spike
Reduce UObject churn; pool objects; tune GC settings (memory-and-gc)
Memory growth
Avoid hard references pulling large assets; stream assets async (asset-management)
Streaming hitches
Prestream assets before they're needed; adjust streaming budget
Gotchas
Profiling in Development/Editor misleads on absolute timing; use Shipping-config
packaged builds for final numbers. Use Development PIE for iteration.
Confusing CPU- and GPU-bound — fix the wrong side. Always read stat unit first.
TRACE_CPUPROFILER_EVENT_SCOPE with a string literal — use _STR variant instead;
passing a quoted string to the plain macro adds extra quotation marks in the name.
DECLARE_CYCLE_STAT in a header — the static DEFINE_STAT it emits causes a
linker duplicate if included in multiple TUs. Use the _EXTERN + DEFINE_STAT pair.
memalloc tracing at scale — capturing every allocation produces enormous traces;
prefer memtag for long sessions and use memalloc only for targeted leak hunts.
Optimizing without measuring — always profile first; fixing a non-bottleneck wastes
time and can obscure the real hotspot.
Stats stripped in Shipping — STATS is 0 in Shipping; use
TRACE_CPUPROFILER_EVENT_SCOPE (disabled by CPUPROFILERTRACE_ENABLED) or
CSV_SCOPED_TIMING_STAT (available in Test/Shipping) for production-visible metrics.
Version notes
Stats2.h is deprecated in 5.6 and redirects to Stats.h; include Stats/Stats.h.
CPUPROFILERTRACE_ENABLED evaluates to 0 in Shipping builds (5.8: CpuProfilerTrace.h:21).
Memory Insights Android callstack support was added in 5.4; available in 5.8.
Timing Insights gained a Verse Sampling track in 5.7.
References & source material
Engine source (UE 5.8, under Engine/Source/Runtime/Core/Public/):