CSV Profiler

A lightweight, scoped, timestamp-based profiler that outputs per-frame timings with separate timelines for the renderthread and gamethread.

Choose your operating system:




This page is published in a draft state in order to make the information available as early as possible. Check back for updates.

The CSV profiler lightweight, scoped, timestamp-based profiler that outputs per-frame timings with separate timelines for the renderthread and gamethread which works on all consoles and also PC and in all builds except shipping.

Capturing Stats to a CSV

On the commandline

Run the executable for your project with the -csvCaptureFrames=N argument to capture N frames from startup:

UE4.exe [Project] -csvCaptureFrames=N

On the console

You can use the csvprofile [start/stop] console command to start or stop capture during runtime. csvprofile frames=N can capture a fixed number of frames


CSV files generated by the CSV Profiler are written out to the [ProjectDirectory]/Saved/Profiling/CSV directory.

Stat Categories

You can define a stat category with CSV_DEFINE_CATEGORY(CategoryName, bEnableByDefault) . You can use an existing category externally with CSV_DECLARE_CATEGORY_EXTERN(CategoryName) . There are _MODULE variants of this for cross-module usage.

Categories via the commandline, with -csvcategories, e.g. -csvcategories="First,Second".

Ideally only key stats should be enabled by default. Plan carefully before making new categories enabled by default, and avoid adding stats to existing categories which are enabled by default unless they're really needed.

Adding Stats

Unit stats and free memory have built-in instrumentation, but you can add your own additonal stats to capture using the CSV_ macros. The CSV_ macros are defined at the top of CsvProfiler.h . You can add the following types of stats:

  • Scoped timing stats - CSV_SCOPED_TIMING_STAT(Category, StatName)

  • Custom (value) stats - CSV_CUSTOM_STAT(Category, StatName,Value, Op) or its variants

    Op is a stat operation enum (ECsvCustomStatOp), which can be one of: Set, Min, Max, Accumulate

See CSVTest() in CSVProfiler.cpp for examples.

Stats can be added inline and do not need to be defined up front. However, you can define them up front if needed. See the CSV_DEFINE_STAT(Category,StatName) and CSV_CUSTOM_STAT_DEFINED macros.

Stats get accumulated on a per-frame basis and written out to a CSV, where each row is a frame, and each column is a stat. They appear as headings in the CSV with CategoryName/StatName , or CategoryName/ThreadName/StatName for timer stats. This convention makes them easy for graphing via the CsvToSvg tool using wilcards. For example:

-stats MyCategory/*


Events can be added with the CSV_EVENT macro which uses the same parameters as printf . Events appear in a special events column in the CSV, separated with semicolons if there are multiple events in a frame. The CSVToSVG graphing tool can be used to annotate graphs with events using the -showevents parameter. See CSVToSVG Tool for more information.

You should try to use events sparingly to capture infrequent occurances. Overuse of events can result in high performance and memory overhead.

GPU Stats

The CSV profiler supports GPU Stats, including in Test builds where STATS is disabled. Recording GPU stats carries some overhead, so it's disabled by default.

To enable recording GPU stats, do one of the following:

  • Set r.GPUCsvStatsEnabled to 1 in the console.

  • Pass -csvGpuStats on the command line.

Performance and Memory considerations

Instrumentation overhead is designed to be as low as possible, enabling you to instrument functions which are called hundreds of times per frame with minimal distortion of the timing data. There is minimal processing of stat data, such as accumulation of timings in thread-local blocks, and these are only processed at the end of the capture.

Raw stat data is processed every 60ms (by default) to reduce memory overhead. The resulting overhead during profiling is 4 bytes per stat per frame and accumulates until the capture ends since nothing is written to disk until that point. This means that memory may become a concern for very long captures with large numbers of stats. Memory usage is summarised to the log at the end of a capture.

Help shape the future of Unreal Engine documentation! Tell us how we're doing so we can serve you better.
Take our survey