CodeFizz
ToolsDemoDocsBlogRoadmapChangelogPricingCompareFAQ
Get the plugin

Getting Started

  • Introduction
  • Quick Start
  • Requirements
  • Installing the CLI
  • License & Machines

Guides

  • Installing the Plugin
  • The AI Skill
  • CLI vs MCP
  • Multiple Editors
  • How It Works
  • Discovering Commands
  • The Editor Chat Panel
  • Image Generation (OpenRouter)

Walkthroughs

  • Build a Blueprint with AI
  • Author a Material Graph
  • Create a Niagara System
  • Rig a Character with AI
  • Build an Animation Blueprint
  • Build Sound with AI
  • Build a Modular Character
  • Grow a Tree with AI
  • Build a Gameplay Ability System
  • Generate a Landscape with AI
  • Work with World Partition

Reference

  • Reference
  • Audio
  • Mutable
  • Control Rig
  • Niagara
  • PCG
  • Procedural Vegetation
  • Materials
  • Gameplay Ability System
  • World Building
  • Behavior Trees
  • Environment Queries
  • StateTree
  • Sequencer
  • Level Actors
  • Project Settings
  • Blueprints
  • Blueprint Structs and Enums
  • Enhanced Input
  • Asset Management
  • Bulk Asset Ops
  • Data Assets
  • Object Properties
  • UMG Widgets
  • Data Tables
  • Curves
  • Retargeting
  • Skeletal Meshes
  • Animation
  • Chooser Tables
  • UAF (Animation Framework)
  • Console Commands
  • Revision Control and Asset Diff
  • Profiling
  • Image Generation
  • Core
  • Debug
  • Mass Entity (ECS)

Help

  • FAQ
  • Troubleshooting
  • For AI Agents
  • Fix: Plugin failed to load, module could not be loaded (GetLastError 126)
  • Fix: bridge unreachable, editor not responding
  • Fix: cfa targeted the wrong Unreal editor
  • Fix: the CodeFizz panel does not show Active
  • Fix: Unknown command, or plugin version mismatch after an update
DocsReferenceProfiling

Profiling

Every Profiling command in CodeFizz Editor Agent, with parameters and examples.

Loading…
PreviousRevision Control and Asset DiffNextImage Generation
CodeFizz

A drop-in Unreal Engine 5 plugin that exposes the entire editor surface (Blueprints, Materials, Niagara, PCG, StateTree, Control Rig, Insights profiling, and more) over the Model Context Protocol. Connect Claude Code, Cursor, VS Code, or any MCP-compatible client and let your AI build inside the engine.

Product

  • Features
  • Docs
  • Tools
  • Blog
  • Demo
  • Roadmap
  • Changelog
  • Pricing
  • Compare
  • FAQ

Resources

  • Install guide
  • Discord
  • YouTube
  • Open-source edition
  • Manage subscription

Legal

  • Refund Policy
  • Privacy Policy
  • Terms of Service

© 2026 CodeFizz. All rights reserved.

CodeFizz Editor Agent is a CodeFizz product. Payments processed by Polar Software, Inc. (Polar), the Merchant of Record.

16 commands. Each shows its parameters and an example, and has a copyable deep link, so you (or an AI agent) can jump straight to one.

performance_start_trace

Start recording a live .utrace from the running editor

Requires UE 5.7+ (all profiling commands do, on a 5.6 editor they return an explanatory error). Begins recording a Unreal Insights .utrace from the running editor. --preset names investigation presets (goal-oriented channel groups); --channels names raw channels. A name that is both a preset and a channel (cpu, gpu, animation) means the CHANNEL inside --channels, write preset:gpu to expand the preset there. The response lists expanded_presets, added_channels (frame and bookmark are always added), channel_notes and high_cost_channels, so nothing heavy is enabled silently. A channel or preset name the engine does not have is refused before anything records, naming the close matches and listing the engine's channels. Run performance_list_channels first to see every channel the engine has. While recording, 'PIE Start' / 'PIE End' bookmarks are written as Play In Editor starts and stops (queries then take --window pie), and a guard stops the trace itself at --max-mb (default 8192, 0 = no limit), --max-seconds, or when the drive falls under --min-free-disk-mb (default 2048; a start with less free space is refused). --until-pie-end stops the trace when PIE ends. Check size and rate with performance_trace_status; stop with performance_stop_trace.

ParameterTypeRequiredDescription
file_pathstringNoOutput file path for connection=file (empty = auto)
presetstringNoInvestigation preset: default,cpu,gpu,render,memory,loading,network,tasks,sampling,animation,uaf
channelsstringNoChannel names and/or preset names, comma-separated (combined with preset). Empty + no preset = engine 'default'
connectionstringNofile (write .utrace) or network (live stream to Unreal Insights)
targetstringNoHost for connection=network (default 127.0.0.1)
exclude_tailboolNoStart without the engine's in-memory tail of the last seconds (smaller trace, and no events from before the start). A trace with the 'net' channel always starts without it
stat_named_eventsboolNoEnable named events (stats.NamedEvents on) so CPU scopes capture stat names
max_mbfloatNoStop the trace itself once this many MB are written (default 8192; 0 = no limit)
max_secondsfloatNoStop the trace itself after this many seconds (default: no limit)
min_free_disk_mbfloatNoRefuse to start, and stop while recording, when the trace drive has less free space than this (default 2048; 0 = off)
until_pie_endboolNoStop the trace itself when the Play In Editor session ends
net_verbosityintNoWith the 'net' channel: the engine's network trace level this trace turns on, because the channel alone records nothing. 1 (default) = packets, objects, properties; 2 and 3 add serializer detail and file size; 0 = leave the level alone. It goes back to what it was when the trace stops
example
cfa performance_start_trace --preset gpu
cfa performance_start_trace --preset memory --exclude-tail
cfa performance_start_trace --channels "cpu,gpu,frame,counters" --until-pie-end
cfa performance_start_trace --channels "preset:gpu,counters" --max-mb 2048
cfa performance_start_trace --connection network --target 127.0.0.1 --preset cpu
cfa performance_start_trace --file-path "C:/Traces/my.utrace" --channels "loading,counters"
performance_stop_trace

Stop recording and optionally auto-load for analysis

Stops the active trace, one started by performance_start_trace, or one started outside CFA (-trace= on the command line, Trace.Start). With auto_load (default) the trace is then analyzed on the engine's background analysis thread: the editor keeps running and PIE keeps playing. The CLI waits for the analysis and returns the loaded trace's summary; pass --wait=false to get the job id at once and poll performance_job_status yourself. A network trace has no file here, so nothing is loaded.

ParameterTypeRequiredDescription
auto_loadboolNoAnalyze the trace after stopping
waitboolNoWait for the background analysis to finish (false = return the job id at once)
wait_timeoutintNoSeconds to wait before returning a still-running job (default 100; 50 over MCP)
example
cfa performance_stop_trace
cfa performance_stop_trace --auto-load=false
cfa performance_stop_trace --wait=false
performance_analyze_insight

Analyze a performance trace (diagnose, spikes, flame, hotpath, etc.)

Requires UE 5.7+ ('objects' query needs 5.8). Runs analysis queries against a loaded .utrace file. The recommended workflow is: (1) performance_start_trace to record, (2) performance_stop_trace to stop and auto-load, (3) performance_analyze_insight with query="diagnose" for a full automatic report, then drill down with "spikes", "flame", "hotpath", or "search" as needed. Use query="load" with trace_path to analyze a previously saved trace. The "diagnose" query returns a one-call verdict with severity findings, category breakdown, and top bottlenecks. The "flame" query shows timers by exclusive (self) time to find actual CPU-consuming code. The "search" query finds a specific timer across all frames with min/avg/max/p95/p99 stats.

ParameterTypeRequiredDescription
querystringYesQuery type (every one runs on a worker thread; the CLI waits for it): unload (free the loaded trace), diagnose, bound, breakdown, calltree, gpu_sync, gpu_passes, inspect_frame, gc, hitch_cause, memory_growth, critical_path, objectproperties, spikes, flame, bottlenecks, hotpath, compare, compare_traces, search, histogram, load, summary, worst_frames, frame_details, timer_stats, butterfly, threads, counters, counter_series, csv, between, net_summary, net_stats, net_packets, net_objects, loading, logs, memory, memory_series, alloc_query, stack_tree, cook, trace_channels, animation, uaf (5.8+), mass, iostore, chaos_locks, render_trace (5.8+), world_streaming (5.8+), regions, bookmarks, session, modules, file_io, tasks, context_switches, allocations, stack_samples, screenshots, objects (5.8+)
trace_pathstringNoPath to .utrace file (for 'load' and 'compare_traces')
frame_indexintNoFrame index (omit = the worst frame in the window)
countintNoResult count (omit = the query's own default; every list reports total/returned/truncated)
threshold_msfloatNoTime threshold in ms (worst_frames/spikes: min frame ms; compare_traces: min self-time delta in ms per game frame, default 0.05)
max_depthintNoMax tree/event depth (query default when omitted)
min_duration_msfloatNoMin event duration for frame_details (default 0.1)
thread_namestringNoThread name filter (frame_details)
threadstringNoThread filter: a CPU thread name (exact, else prefix), or GPU. stack_samples: every sampled thread whose name contains it
filterstringNoName filter (substring). For 'uaf': variable names
start_timefloatNoWindow start in seconds
end_timefloatNoWindow end in seconds
include_valuesboolNoInclude counter values
max_samplesintNoMax samples per counter (default 100)
timer_namestringNoTimer name (butterfly / calltree)
counter_idintNocounter_series: exact counter id from --query counters (names can repeat)
modestringNobutterfly: callers, callees or both (default both); calltree: callees or callers (default callees)
connection_indexintNoNetwork connection index, global across game instances (0..N-1). net_summary lists every index with its sent and received bandwidth; net_packets/net_objects default to the first connection with data; net_stats aggregates outgoing traffic only when this is given
verbositystringNoLog verbosity filter
trackerintNoMemory tracker id (default: the tracker named Default, else the first; the result names the tracker used)
target_fpsfloatNoTarget FPS for budget checks (default 60)
categorystringNoCategory filter
event_namestringNoEvent name filter
min_deviation_pctfloatNocompare: min deviation from the median to report (default 50)
bucket_size_msfloatNoHistogram bucket size (default: auto from target fps)
snapshot_indexintNoSnapshot index for the 'objects' query (default: the last snapshot at or before the window end)
skip_framesintNoWarmup frames to skip for 'bound'/'diagnose' (omit = auto-detect startup spikes)
warmup_secondsfloatNoSkip frames in the first N seconds of the window for 'bound'/'diagnose'
skip_waitsboolNoFor 'calltree': skip Wait/Idle children in the hot path to land on the real work leaf
objectstringNoFor 'objectproperties': traced object name (substring). Omit to list traced objects. For 'uaf': substring of the instance's asset or owner
object_idstringNoFor 'objectproperties' and 'animation': trace object id, passed as the string (trace_object_id from performance_trace_object, or an id the query listed). Use it when names repeat, e.g. one object per PIE world
propertystringNoFor 'objectproperties': a property name; the exact name and its .Member children match first, else a substring. Returns the points where each value changed
namestringNoFor 'counter_series': counter name (substring, case-insensitive). Omit to list all counters
fromstringNoWindow start anchor for any windowed query: a bookmark text (substring) or a seconds value
tostringNoWindow end anchor: a bookmark text (first match at or after --from) or a seconds value
capture_idintNoFor 'csv': capture id to read (default: first capture)
queuestringNoFor 'gpu_passes': GPU queue filter (e.g. Graphics, Compute)
wait_secondsfloatNoFor 'alloc_query': max seconds to wait for results (max 60)
rulestringNoFor 'alloc_query': allocation rule, aAf (live at A), AaBf (growth A..B), AaBCf (leaks), AafB (short-living), aABf (long-living)...
time_afloatNoFor 'alloc_query': time marker A in seconds (default: trace end)
time_bfloatNoFor 'alloc_query': time marker B in seconds
time_cfloatNoFor 'alloc_query': time marker C in seconds
time_dfloatNoFor 'alloc_query': time marker D in seconds
directionstringNoFor 'net_packets'/'net_objects': out or in (default out)
packet_startintNoFor 'net_objects': first packet index of the analysis window (default 0); net_packets largest_packets[].packet_index values plug in here
packet_countintNoFor 'net_objects': packets to analyze from packet_start (default 2000)
viewstringNoFor 'gpu_passes': flat (default) or tree. For 'animation': overview, tickrecords, graph, notifies (notifies, notify states and sync markers), montages (with --object; omit --object to list animated objects)
enable_analyzerboolNoFor 'render_trace': opt in to the RenderTrace analyzer (disabled by default, a UE 5.8 engine bug can crash the editor on mid-session traces)
windowstringNoAnalyze only part of the trace: pie (first Play In Editor session), pie:N, pie:last, or full. Works on every windowed query; --from/--to and --start-time/--end-time are the other ways to set a window
name_modestringNoGPU pass names: digits (default: numbers folded to # so per-frame and per-resolution variants add up), full (exact names), timer (static timer name only)
allow_partialboolNoQuery a trace whose background analysis has not finished yet (results cover only what is analyzed so far). mass, chaos_locks and cook always wait for the full analysis, and on 5.8 so do animation and objectproperties
waitboolNoWait for the background job (the load, or the query on its worker thread) to finish (false = return the job id at once)
wait_timeoutintNoSeconds to wait before returning a still-running job (default 100; 50 over MCP)
example
cfa performance_analyze_insight --query diagnose
cfa performance_analyze_insight --query bound --target-fps 60
cfa performance_analyze_insight --query bound --skip-frames 30
cfa performance_analyze_insight --query breakdown --thread GPU --count 15
cfa performance_analyze_insight --query breakdown --thread GameThread
cfa performance_analyze_insight --query calltree --timer-name "FTickFunctionTask" --max-depth 8
cfa performance_analyze_insight --query calltree --timer-name "FEngineLoop::Tick" --thread GameThread --skip-waits
cfa performance_analyze_insight --query gpu_sync
cfa performance_analyze_insight --query gpu_passes --count 20
cfa performance_analyze_insight --query gpu_passes --filter Shadow
cfa performance_analyze_insight --query inspect_frame --frame-index 137
cfa performance_analyze_insight --query objectproperties
cfa performance_analyze_insight --query objectproperties --object BP_Miner --property StoredAmount
cfa performance_analyze_insight --query counter_series
cfa performance_analyze_insight --query counter_series --name "DrawCall" --count 200
cfa performance_analyze_insight --query between --from MARK_A --to MARK_B
cfa performance_analyze_insight --query between --from 5 --to 10 --count 15
cfa performance_analyze_insight --query gc
cfa performance_analyze_insight --query hitch_cause
cfa performance_analyze_insight --query hitch_cause --frame-index 137
cfa performance_analyze_insight --query csv
cfa performance_analyze_insight --query csv --filter DrawCalls --count 200
cfa performance_analyze_insight --query compare_traces --trace-path "C:/Traces/after.utrace"
cfa performance_analyze_insight --query memory_growth --count 15
cfa performance_analyze_insight --query critical_path
cfa performance_analyze_insight --query critical_path --frame-index 137
cfa performance_analyze_insight --query load --trace-path "C:/Traces/my_trace.utrace"
cfa performance_analyze_insight --query spikes --count 5 --target-fps 60
cfa performance_analyze_insight --query flame --count 10 --thread GameThread
cfa performance_analyze_insight --query hotpath --frame-index 42 --category Animation
cfa performance_analyze_insight --query search --filter "ConveyorProcessor" --count 10
cfa performance_analyze_insight --query butterfly --timer-name "MassProcessor" --mode both
cfa performance_analyze_insight --query frame_details --frame-index 100 --max-depth 5 --min-duration-ms 0.5
performance_list_channels

List every trace channel the running engine has (engine + custom) plus presets

Enumerates all trace channels registered in the running editor, engine channels AND any custom channels defined by plugins, each with its enabled state, category, cost, a one-line summary, and when to use it. Also returns the named investigation presets. Run this BEFORE performance_start_trace to decide exactly what to capture for a target. Filter by name/desc substring, by category (CPU, GPU, Memory, Loading, Network, Gameplay..., Custom for channels the catalog does not describe; an unknown category is refused with the valid ones), or show only currently-enabled channels. --max-results caps the list; the response reports total, returned and truncated.

ParameterTypeRequiredDescription
filterstringNoSubstring match on channel name or description
categorystringNoFilter by category (CPU, GPU, Memory, Loading, Network, Gameplay, UI, Physics, Core, Custom...); an unknown one is refused
enabled_onlyboolNoOnly channels currently enabled
include_presetsboolNoInclude the investigation presets in the output
max_resultsintNoCap on channels returned; 0 = all
example
cfa performance_list_channels
cfa performance_list_channels --category Memory
cfa performance_list_channels --filter mass
cfa performance_list_channels --enabled-only
performance_toggle_channel

Enable or disable a trace channel at runtime (mid-trace)

Enables or disables a single trace channel on the running engine without restarting the trace. Use it to add a channel mid-session once you've narrowed down a suspect, or to drop an expensive channel. Channel name is matched leniently (case-insensitive, optional 'Channel' suffix).

ParameterTypeRequiredDescription
channelstringYesChannel name (e.g. cpu, mass, memalloc)
enabledboolNotrue to enable, false to disable
example
cfa performance_toggle_channel --channel mass
cfa performance_toggle_channel --channel memalloc --enabled=false
performance_trace_bookmark

Insert a named bookmark into the live trace timeline

Emits a named bookmark into the active trace so you can mark exactly when something happened (e.g. 'spawned 10k belts') and find it later in performance_analyze_insight --query bookmarks. Only recorded while a trace is active with the 'bookmark' channel enabled.

ParameterTypeRequiredDescription
namestringYesBookmark label
example
cfa performance_trace_bookmark --name "spawned 10k belts"
performance_trace_snapshot

Write a trace snapshot (tail buffer) to a .utrace file

Writes the current in-memory trace tail to a .utrace file without stopping the recording. Useful to capture the moments leading up to a spike you just saw. Leave file_path empty for an auto-generated path under the project's Profiling directory.

ParameterTypeRequiredDescription
file_pathstringNoOutput snapshot path (empty = auto)
example
cfa performance_trace_snapshot
cfa performance_trace_snapshot --file-path "C:/Traces/spike.utrace"
performance_trace_screenshot

Capture a screenshot into the live trace

Requests a screenshot to be embedded into the active trace on the next frame, so you can visually correlate the viewport with a timing spike in Unreal Insights. Needs an active trace with the 'screenshot' channel enabled; with the channel off the request is refused (the engine would capture nothing), so turn it on with performance_toggle_channel --channel screenshot first.

ParameterTypeRequiredDescription
namestringNoScreenshot label (default CFA_Screenshot)
show_uiboolNoInclude editor UI in the capture
example
cfa performance_trace_screenshot --name "before-spike"
performance_trace_object

Register UObject(s) for per-frame property tracing (objectproperties query)

Registers actors (matched by name and/or class in the editor/PIE world) so the trace records their UObject property values every frame, and enables the 'object' + 'objectproperties' channels. Object-property tracing is opt-in per object, nothing is recorded until you register. After registering, record (or keep recording) a trace, then read the values back with performance_analyze_insight --query objectproperties --object <name>. Pass --enabled=false to unregister: the channels stay on while any registered actor remains, and unregistering the last one turns off only the channels registering turned on. A name/class that matches no actor is refused with the closest labels and classes.

ParameterTypeRequiredDescription
namestringNoActor label/name substring to match
classstringNoClass-name substring to match (combine with name to narrow)
enabledboolNotrue to register for tracing, false to unregister
countintNoMax objects to register
example
cfa performance_trace_object --name BP_Miner
cfa performance_trace_object --class StaticMeshActor --count 5
cfa performance_trace_object --name BP_Miner --enabled=false
performance_live_start

Start sampling live per-frame timing (no trace needed)

Begins sampling the engine's per-frame timing counters every frame (frame time plus game/render/rhi/gpu thread ms) via FCoreDelegates::OnEndFrame. No trace and no 'stat unit' are needed, it reads the always-fresh engine counters directly. Let the editor or PIE run for a while, then call performance_live_stop to get the distribution across all sampled frames (min/avg/max/p50/p95/p99 + avg and 1%-low fps), so a single biased frame can't mislead. Sampling self-stops at --max-frames.

ParameterTypeRequiredDescription
max_framesintNoStop sampling automatically after this many frames
example
cfa performance_live_start
cfa performance_live_start --max-frames 600
performance_live_stop

Stop live sampling and return the multi-frame timing distribution

Stops the live sampler started by performance_live_start and returns the distribution over all sampled frames: for frame time and each of game/render/rhi/gpu thread ms, the min/avg/max/p50/p95/p99, plus avg fps and 1%-low fps (1000 / p99 frame ms, worst-case smoothness). frame_ms reflects displayed frame time (vsync / t.MaxFPS / editor throttle capped); the thread and gpu ms show the actual per-thread work. The stop ends the session: a second stop is refused until performance_live_start runs again.

example
cfa performance_live_stop
performance_trace_status

Recording state (MB written, rate, limits) and background analysis progress

Reports whether a trace is recording, CFA's or one started outside CFA, with its destination, active channels, MB written, MB per minute, elapsed time, limits and free disk space, plus why the last recording stopped itself (max_mb, max_seconds, low disk, PIE end). Also reports the loaded trace's background analysis: percent of the file read, trace seconds analyzed so far, and whether it is complete.

example
cfa performance_trace_status
performance_job_status

Progress or final result of a background profiling job

Profiling work that needs real frames to pass (trace analysis after stop/load, GPU captures, console-variable A/B runs) runs as a job so the editor never freezes. The CLI waits for jobs by itself; use this to poll one started with --wait=false, to list current jobs (no --job-id), or to cancel one (--cancel restores anything it changed, such as console variables). Finished jobs are kept for 30 minutes.

ParameterTypeRequiredDescription
job_idintNoJob id from a command's response (omit to list jobs)
cancelboolNoStop the job and restore anything it changed
example
cfa performance_job_status
cfa performance_job_status --job-id 3
cfa performance_job_status --job-id 3 --cancel
performance_profile_gpu

Capture N frames of GPU timing and return the pass tree (ProfileGPU as JSON)

Requires UE 5.7+. Records its own short trace (gpu, frame and bookmark channels) over --frames frames after --warmup-frames, with r.RDG.Events 3 so every RDG pass has its name (what ProfileGPU forces; --pass-names=false keeps the project's setting), then loads that trace and returns the GPU pass hierarchy per queue averaged per frame: ms = busy time, self_ms = minus children, calls = instances per frame, max_ms = worst single instance. No log parsing and no ProfileGPU pop-up. --root keeps only subtrees whose name contains it (like r.ProfileGPU.Root), --threshold-ms and --max-depth fold small or deep nodes into 'hidden', --view flat lists passes by self time instead. --cvars applies console variables only for the capture. A bad --view, --name-mode or console variable is refused before anything records. Every changed variable and every channel it turned on is put back; the response lists them. The capture trace stays loaded, so gpu_passes, breakdown --thread GPU and calltree --thread GPU can drill further. Refused while another trace is recording. The CLI waits for the result (--wait=false returns the job id).

ParameterTypeRequiredDescription
framesintNoFrames to measure (default 60)
warmup_framesintNoFrames to let pass before measuring (default 30)
rootstringNoKeep only subtrees whose pass name contains this text (like r.ProfileGPU.Root)
viewstringNotree (default, the pass hierarchy) or flat (passes by self time)
threshold_msfloatNoTree: fold nodes under this many ms per frame into 'hidden' (default 0.05)
max_depthintNoTree: deepest level shown (default 6)
countintNoTree: children shown per node (default 12). Flat: rows (default 25)
queuestringNoOnly GPU queues whose name contains this (e.g. Graphics, Compute)
name_modestringNodigits (default: numbers folded to #), full (exact names), timer (static timer name only)
cvarsstringNoConsole variables set only for the capture: "r.Foo=1,r.Bar=0"
pass_namesboolNoSet r.RDG.Events 3 during the capture so every RDG pass is named (default true)
timeout_secondsintNoGive up (and restore everything) after this many seconds (default 300)
waitboolNoWait for the result (false = return the job id at once)
wait_timeoutintNoSeconds to wait before returning a still-running job (default 100; 50 over MCP)
example
cfa performance_profile_gpu
cfa performance_profile_gpu --frames 120 --root Shadow --threshold-ms 0.1
cfa performance_profile_gpu --view flat --count 30
cfa performance_profile_gpu --cvars "r.Shadow.Virtual.Cache=0"
performance_ab

Console-variable A/B test: frame, stage, GPU pass and CPU timer deltas

Requires UE 5.7+. Measures phase A, then phase B, in one short trace (cpu, gpu, frame, bookmark): each phase sets its console variables, lets --warmup-frames pass, then bookmarks --frames measured frames. Phase A keeps the current values unless --a is given. After both phases every variable is put back to its old value and priority, the trace is loaded, and the result has per-phase frame median and p95, stage medians (game, render, RHI thread, GPU), GPU queue busy time, and the GPU passes and CPU timers whose self ms per frame moved by at least --threshold-ms, with B minus A deltas. One variable: --cvar NAME --a 1 --b 0. Several: --a "r.Foo=1,r.Bar=2" --b "r.Foo=0,r.Bar=0". The editor keeps running between steps; the CLI waits for the result. Refused while another trace is recording.

ParameterTypeRequiredDescription
cvarstringNoOne console variable to test; --a and --b are then its two values
astringNoPhase A: the value for --cvar, or "name=value..." (omit to keep the current values)
bstringYesPhase B: the value for --cvar, or "name=value..."
framesintNoFrames measured per phase (default 120)
warmup_framesintNoFrames to let pass after each change before measuring (default 30)
threshold_msfloatNoSmallest per-frame change listed for GPU passes and CPU timers (default 0.02)
countintNoRows per regressed / improved list (default 8)
pass_namesboolNoSet r.RDG.Events 3 during the test so every RDG pass is named (default true)
timeout_secondsintNoGive up (and restore everything) after this many seconds (default 300)
waitboolNoWait for the result (false = return the job id at once)
wait_timeoutintNoSeconds to wait before returning a still-running job (default 100; 50 over MCP)
example
cfa performance_ab --cvar r.Shadow.Virtual.Cache --a 1 --b 0
cfa performance_ab --cvar ShowFlag.SkeletalMeshes --b 0 --frames 240
cfa performance_ab --a "r.Lumen.ScreenProbeGather.DownsampleFactor=16" --b "r.Lumen.ScreenProbeGather.DownsampleFactor=32"
performance_vsm_report

Virtual shadow map page cache report: cached vs redrawn pages per frame

Requires UE 5.7+. Sets r.Shadow.Virtual.AccumulateStats to --frames, so the renderer writes its own per-frame VSM page stats to Saved/Profiling/VSMStats(<time>).csv, then reads that file: static_pages and dynamic_pages give cached vs redrawn pages per frame and redrawn_pct (a static cache redrawn every frame shows at once), and stats lists every non-zero engine stat column (avg, min, max, last). No trace is recorded, so values are exact per frame. --visualize MODE then renders the level viewport once in that VSM visualization mode (r.Shadow.Virtual.Visualize with the VisualizeVirtualShadowMap show flag forced on: cache shows red = all invalidated, blue = dynamic invalidated, yellow-green = force cached, untinted = cached; also invalid, dirty...; an unknown mode lists the valid ones) and saves a PNG. Everything is put back afterwards, including r.ShaderPrint, which the engine's stats pass switches on. Needs virtual shadow maps in view and the level viewport rendering.

ParameterTypeRequiredDescription
framesintNoFrames of stats to collect (default 60)
visualizestringNoVSM visualization mode for one viewport screenshot (cache, invalid, dirty...)
screenshot_pathstringNoPNG path for --visualize (default Saved/Profiling/VSM_<mode>_<time>.png)
timeout_secondsintNoGive up (and restore everything) after this many seconds (default 300)
waitboolNoWait for the result (false = return the job id at once)
wait_timeoutintNoSeconds to wait before returning a still-running job (default 100; 50 over MCP)
example
cfa performance_vsm_report
cfa performance_vsm_report --frames 120 --visualize cache
cfa performance_vsm_report --visualize invalid --screenshot-path "C:/Temp/vsm_invalid.png"