FPS meter and render profiling

Senzoukria ships two frame-rate readouts, a global meter toggled with Ctrl+Shift+F and a per-chart counter next to the price axis, plus a render pass profiler whose timings go to the console in development or when opted in.

Senzoukria · Documentation · Updated September 2026


Where to find it

Global meter
Ctrl+Shift+F toggles it; the choice is remembered between launches
Chart counter
Top of the chart, left of the price axis, refreshed every 500 ms
Rendering sharpness
Settings → Performance → 1×, 1.5× or 2×; default 1.5×
Pass profiler output
Console lines tagged [fp-perf], once per second, dev builds or opt-in

What it does

The global FPS meter is a diagnostic strip meant to be switched on for thirty seconds to check a number. It shows frames per second over the last second, the worst frame time in that second in milliseconds, the detected screen refresh rate (median of 60 frame intervals measured at mount), and, after the window regains focus, the average and minimum FPS measured while it was in the background. That last figure answers whether the app is being throttled behind another application. When Windows requests reduced motion, the strip says animations OFF (Windows), because the background is then deliberately frozen.

The chart counter is a different measurement: since September 2026 it counts the frames the main thread actually delivers to the screen while the chart is visible, not the number of repaints. It therefore follows the panel rate (60, 100, 144, 240) and drops only on a real stutter. The repaint count stayed in the [fp-perf] logs, under painted=. A pause longer than one second without a frame, for instance a hidden chart or a minimised window, restarts the measurement instead of counting as a stall, and the chart itself still paints only when something changes, through a frame loop that keeps at most one pending frame and none while the chart is hidden.

Readouts and thresholds

Colours as computed in the code
ReadoutGreenYellowRed
Global meter (vs detected refresh rate)≥ 92 % of the refresh rate≥ 70 %below 70 %
Chart counter (vs best of the last 10 readings)≥ 90 % of the recent peak and ≥ 50 fps≥ 70 % of the peak, or 30 to 49 fpsbelow 70 % of the peak, or under 30 fps
Background statsminimum ≥ 60 fpsminimum below 60 fps

Settings

What changes render cost
SettingDefaultWhat it changes
Rendering sharpness1.5×Cap on the canvas pixel ratio. 1× halves the pixels on HiDPI screens; 2× is sharpest and heaviest. Options: 1×, 1.5×, 2×.
Performance modeBalancedPerformance sets 1×, Balanced 1.5×, Precision 2× (together with other knobs). Touching a knob by hand switches the mode to Manual.
Perf logsOff in release buildsSet localStorage senzoukria.perfLogs to 1 and reload to enable the [fp-perf] console lines on a release build.

Render pass profiling

Every drawing pass of the footprint renderer (cells, profiles, GEX levels, news markers, the DOM panel commit, React commits) is timed through a shared profiler. Once per second the canvas flushes it and prints a ranked line to the console: total and average milliseconds per pass, the worst pass, the number of React commits and the DOM panel cost. The profiler holds no reference to the canvas or React, and popout windows have their own instance, so measurements never mix across windows.

These logs are silent in distributed builds because the WebView console retains what it is written, and a log per second over hours is a memory cost. They are on in npm run dev and can be enabled on a user's machine with the opt-in key above.

Limits or pitfalls

Reading the numbers:

  • The chart counter stops rather than reports zero: when the chart is hidden or the window inactive, the measurement is paused and restarts from scratch on the next frame.
  • Colours are relative to the recent peak, so the same 120 fps reads green on a 120 Hz screen and amber on a 240 Hz one.
  • The detected refresh rate is a median of frame intervals; on a machine that cannot keep up it can read below the true panel rate.
  • The global meter runs its own requestAnimationFrame loop; leave it off outside diagnostics.
  • Background measurements need the window to lose focus and come back; the strip shows the last background period only.

This page in other languages

Frequently asked questions

How do I show the FPS meter?
Press Ctrl+Shift+F. Press it again or click ✕ to hide it. The state is stored under senz.fpsMeter and restored at the next launch.
The chart counter reads 45 fps on a 144 Hz monitor. What does that mean?
It means the main thread delivered 45 frames in the last second while the chart was visible, so something is holding it up. The colour is relative: green needs at least 90 % of the best of the last ten readings and 50 fps, and anything under 30 fps is red whatever the screen. Compare with the global meter, which measures the animation loop against the detected refresh rate.
Where are the render profiling numbers?
In the developer console as [fp-perf] lines once per second, available in development builds or after setting localStorage senzoukria.perfLogs to 1 and reloading.

Keep reading