22 fps, 20 minutes: profiling triage
Rule out settings, then measure, then fix. stat unit tells you which thread is the
bottleneck: Game, Draw or GPU. Each has completely different causes and fixes. Don't guess "it's an artist's level so it's
the GPU".
Step 1: the free stuff (2 minutes)
- Scalability set to Cinematic? Screen percentage over 100?
- Running in an editor viewport rather than standalone?
- "Texture streaming pool over budget" warning? Unbuilt lighting?
- Turn off vsync / frame cap (
t.MaxFPS 0) before trusting any numbers. A cap flatters the GPU time.
Step 2: stat unit: which thread?
| Frame ≈ | Bottleneck | Typical causes | Fix direction |
|---|---|---|---|
| Game | Game thread | Blueprint Tick on hundreds of actors, heavy per-frame logic | Tick less (Tick), managers, move hot loops to C++ |
| Draw | Render thread, usually draw calls | 300 separate foliage actors; each shadow-casting light multiplying draws | Instancing (ISM/HISM/Nanite), merging, cull distances, fewer shadow casters |
| GPU | GPU | Overdraw (translucency), shader cost, Lumen settings | Simpler materials, static switches, Lumen quality |
Foliage usually hits Draw before GPU. Your mock answer gave three causes, all on the GPU. The question wanted three bottlenecks.
Step 3: narrow it
- View modes: Shader Complexity, Quad Overdraw, Light Complexity, Lightmap Density.
stat rhi(draw calls, primitives),stat game,stat scenerendering.ProfileGPUfor per-pass GPU cost. Unreal Insights for a real trace across threads.
Corrections worth remembering
- Masked isn't automatically cheaper than translucent. Masked avoids blending and sorting but breaks early-Z, so dense masked foliage still pays heavy quad overdraw. It's usually still right for foliage; just say why.
- Lights: point = 6 shadow faces vs spot = 1 is right. The bigger levers: is it movable, does it cast shadows at all, and how big is its attenuation radius. Turning off shadows on a decorative light is often the biggest one-minute win.
- Your static-switch point (a lerp that's only ever 0 or 1 should be a static switch parameter) is a real "I've optimised a material" answer. Keep it.
"First I check it isn't a settings problem: scalability, screen percentage, standalone vs editor. Then stat
unit with the frame cap off, to see whether Game, Draw or GPU is the bottleneck, because the fixes are completely
different. Game thread means Tick and Blueprints, Draw means draw calls and instancing, GPU means overdraw, shader cost
or Lumen. Then I narrow it with view modes and ProfileGPU if it's the GPU. With 20 minutes I'd go for the
biggest reversible win, usually shadow casting or cull distances, and log the rest for after the milestone."
Run stat unit on a real level (WadOfGore once it has enemies), screenshot it, and be able to say which
thread is bound and how you'd confirm it.
Quiz yourself
What's the first command, and what four numbers does it give?
stat unit: Frame, Game, Draw, GPU (plus RHIT and others in newer versions).
Frame ≈ Draw. What's the likely cause and fix?
Too many draw calls (many separate meshes, shadow-casting lights). Fix: instancing / merging / cull distances / fewer shadow casters.
Why turn off vsync before reading stat unit?
A frame cap pads the frame time, so the numbers don't show the real bottleneck.
Why can dense masked foliage still be expensive?
Masked materials break early-Z, so hidden pixels still get shaded. That's heavy quad overdraw.
Three light settings that matter more than point vs spot.
Mobility (movable?), cast shadows on/off, attenuation radius.
Name three optimisation view modes.
Shader Complexity, Quad Overdraw, Light Complexity (also Lightmap Density).