Game Profiling and Optimization
Players do not experience average frame rates; they experience frame times. A game that averages 60 FPS but hitches for 200 ms every time a new area loads, a shader compiles, or the garbage collector runs feels worse than a steady 45. Optimization is therefore about the whole distribution of frame times — consistent pacing, no stutters — within strict per-frame budgets on every target device.
The most important rule is to measure first. Intuition about performance is usually wrong: the "expensive" particle system may be cheap while a forgotten debug draw or an uncached GetComponent call in a hot loop dominates. Profilers, captures, and automated performance tests turn guesses into evidence and keep improvements from regressing.
TL;DR
- Work to a frame budget: 16.7 ms at 60 FPS, 33.3 ms at 30, 8.3 ms at 120 — split across game, render, and GPU work.
- Track frame-time percentiles and stutters, not average FPS.
- First determine whether you are CPU-bound or GPU-bound, then use the matching profiler.
- CPU costs: scripts, physics, animation, draw call submission, and garbage collection; GPU costs: overdraw, shaders, resolution, shadows, post-processing.
- Budget memory per platform and stream assets; eliminate hitches from loading and shader compilation.
- Automate performance tests on target hardware and watch thermal throttling on mobile and handhelds.
Quick Example
Summarizing a frame-time capture exported from a profiler or an in-game logger:
Adding a named marker so custom systems show up in the Unity Profiler:
Core Concepts
Frame Budgets and Pacing
Divide the budget among systems — gameplay, physics, animation, AI, rendering submission, audio — and leave headroom for spikes. Frame pacing matters as much as average speed: uneven frame delivery feels like stutter even at high FPS, so use platform pacing and VSync features properly.
CPU-Bound or GPU-Bound?
CPU and GPU work in parallel, offset by a frame or more. If the GPU finishes early and waits, the game is CPU-bound; if the CPU waits on the GPU, it is GPU-bound. Quick tests: lower the render resolution — if frame time drops, you are GPU-bound; if not, look at the CPU. Engine stats (Unreal's stat unit, Unity's Profiler CPU and GPU modules) show both sides.
CPU Costs
See Game Loops and ECS and Memory Management.
GPU Costs
Memory and Loading
Set memory budgets per platform for textures, meshes, audio, and code, and track them per level. Stream assets asynchronously, compress textures with GPU formats, and avoid loading on the main thread. Two common sources of hitches: synchronous asset loads and shader compilation at first use — fix the latter with pipeline-state caches, precompilation, or warm-up passes. See Game Asset Pipelines.
Tools
Profile development or profiling builds on target hardware, not the editor: editors add overhead and hide real costs.
Regression Testing and Thermal Limits
Automate performance tests: scripted camera flythroughs and gameplay scenarios run on representative devices in CI, recording frame-time percentiles, memory, and load times per build, and failing when budgets are exceeded. Mobile devices, handhelds, and laptops throttle under sustained heat, so measure long sessions, not just the first minutes, and offer quality presets and frame-rate caps.
Best Practices
Measure on Target Hardware
Profile builds on the slowest supported devices with realistic scenes and long sessions.
Optimize the Biggest Cost First
Use profiler data to find the dominant cost and confirm each change with a new measurement.
Eliminate Hitches, Not Just Averages
Track p99 frame times and stutter counts; fix loading, allocation, and shader compilation spikes.
Guard Against Regressions
Automate performance captures and budgets so improvements stay improved.
Common Mistakes
Optimizing in the Editor
Average FPS as the Only Metric
Per-Frame Allocations
FAQ
What is a frame budget?
The time available to produce one frame at the target frame rate — 16.7 ms at 60 FPS — which must cover gameplay, physics, rendering submission, and GPU work.
How do I know if my game is CPU-bound or GPU-bound?
Use engine statistics showing CPU and GPU frame times, or reduce rendering resolution: if frame time drops significantly, the game is GPU-bound; otherwise the CPU is the bottleneck.
What causes stutter in games?
Frame-time spikes from shader compilation, synchronous asset loading, garbage collection, physics or AI spikes, and uneven frame pacing.
What is overdraw?
Shading the same pixel multiple times per frame, typically from overlapping transparent surfaces such as particles and UI, which consumes GPU fill rate.
Should I profile in the editor?
Use the editor for quick checks, but make decisions based on development or profiling builds on target hardware, since the editor adds overhead and behaves differently.
Related Topics
- Game Development — Building games
- Web Performance — Performance budgets in another domain
- Shader Programming — GPU costs and optimization
- Game Loops and ECS — Structuring per-frame work
- Memory Management — Allocation and garbage collection
- Game Asset Pipelines — Compression, LODs, and streaming