ermod-engine

Finding stutters

On this page

The engine has a built-in frame tracer. It records how long every frame took while you play and flags the stutters. When asked, it also notes which of the game's code was running and how long the GPU spent on each piece of work. Afterwards, ermod-engine trace report says what made the slow frames slow.

It needs no mod. It is part of the engine, off by default, and you switch it on when you want it.

Turn it on

While the game runs, from a terminal:

ermod-engine trace start              # frame timing, plus CPU sampling at the "normal" level
ermod-engine trace start --gpu        # frame timing, plus GPU timing
ermod-engine trace start --cpu detailed --gpu
ermod-engine trace stop

Start a trace when a stutter shows up, play through it, then stop. Changing what is traced while a trace is running starts a new trace file.

From launch, in engine.cfg (see Settings):

frame_trace_cpu = "normal"   # "off", "light", "normal" or "detailed"
frame_trace_gpu = true

Both are off by default. With either one on, a trace starts as the game does and runs until trace stop or until the game exits.

Option What it adds
every trace each frame's time, split into the game's CPU work, waiting on the GPU or display, and the engine's own work
--cpu light which game code and which libraries run during stutters, sampled about 50 times a second
--cpu normal the same, about 100 times a second; enough for most stutters
--cpu detailed the same, about 250 times a second; for catching a single short stutter
--gpu the GPU time of each batch of work the game submits

Read the report

ermod-engine trace report               # the newest trace
ermod-engine trace report <file.ftr>    # a specific one

Traces are written into the game's prefix, under drive_c/ermod/trace/; trace start prints the full folder for your setup. A report starts with the frames:

trace 2.7.1.0  2764 frames  47.3 s  58.4 fps
interval  p50 16.9 ms  p99 22.5 ms  p99.9 81.3 ms   spikes 7
spikes by side  cpu 6  present/gpu 0  engine 1
worst spikes  (ms: total = cpu + engine + present, mods)
  +47.3 s  95.4 = 94.5 + 0.8 + 0.1   mods 0.3

With --cpu, the report adds tables that compare slow frames against normal ones:

Functions are named by their offset in the game (game+0x1ed80f0). They are the same on every machine with the same game build, so two people's reports can be compared.

With --gpu, the report adds the GPU time per frame and per batch of work. It first checks that the game submits its work in the same order from frame to frame. The game does not always do so, and the per-batch rows only use frames where it did. If too few stutters fall in such frames, the report says so instead of guessing.

What it costs

Tracing is designed not to cause the stutters it measures. Nothing it does while you play waits on a file or a lock; a separate thread writes the trace four times a second.

How much CPU sampling slows frames down has not been measured precisely yet. If a trace looks worse than the game feels, try --cpu light.

Sharing a trace

A trace with frame timing alone is about 120 KB a minute; with CPU sampling it is a few MB a minute. It holds timings, code offsets and the names of the libraries loaded into the game. With CPU sampling, each sample also holds a raw 1 KB copy of the sampled thread's stack, which can contain fragments of whatever the game had in memory at that moment. The report's text holds none of that. Attach the report's text to a bug report first, and the .ftr file only if you are asked for it.

For mod authors

sdk.perf.spikes() counts stutters with the same rule, without a trace running. See perf and examples/perf_monitor.lua.