OTOM SPH Benchmark Guide

The Bench tab runs an SPH fluid simulation on your GPU (a reference scene, a showcase demo or your own scene) with each renderer, and measures how fast your hardware can actually drive it, without the frame-rate cap of your monitor. This page explains what is measured, how, and how to get results you can compare between machines.

1. Quick start

  1. Open the Bench tab in the left rail.
  2. Choose a Scene. Dam break (reference) is the default and the one to use for comparing machines.
  3. Choose a Duration per test. 20 s is a good default; 5 s gives a quick check but noisier numbers; use 60 s or more to see thermal throttling on laptops.
  4. Tick the tests you want. The estimate under the list shows the total run time.
  5. Press Start and keep the browser tab visible until it finishes.
  6. Read the results table and score, then save them with HTML Report, CSV, JSON or Copy.

Whichever scene you benchmark, your own settings are saved before the run and restored afterwards: renderer, container, obstacles, particles, colours, camera and play state. The simulation itself restarts from its initial state, as it does whenever a scene is loaded.

2. Why "uncapped" FPS

A browser draws a new frame when the monitor refreshes. The usual FPS counter therefore counts screen refreshes, and it cannot go above your monitor's refresh rate (60, 120, 144 Hz…). A scene your GPU could run at 1,000 frames per second and one that barely makes 60 both read "60".

The benchmark instead measures how long one frame's work really takes on the GPU and CPU. The uncapped frame rate is simply one second divided by that time: the rate your hardware could sustain if nothing were holding it back to the monitor's pace.

Uncapped FPS = 1000 / frame time (ms) frame time = max(GPU time from frame start to frame end, CPU time spent preparing the frame)

3. How a frame is timed

The simulation runs on the GPU through WebGPU. Each frame, the app asks the GPU to record three high-resolution timestamps at precise points in its work queue:

Simulation (SPH substeps) Render t0 t1 t2 GPU Sim = t1 − t0 GPU Render = t2 − t1 GPU frame time = t2 − t0

Because work is sent to the GPU in several pieces while the CPU prepares the next ones, t2 − t0 measures the real critical path. If the GPU is the bottleneck it is pure GPU execution time; if the CPU is slow to prepare work, the GPU waits between pieces and that waiting is included too. The CPU time the app spends preparing the frame is measured separately, and the larger of the two is used as the frame time.

Timing source. This needs the WebGPU timestamp-query feature, available in current desktop Chrome and Edge. The benchmark panel shows which method is in use. Where it is missing (for example some Firefox or Safari versions), the app falls back to measuring wall-clock time until the GPU reports the frame finished. That fallback includes a little reporting delay, so it reads lower than the truth on very light scenes, and is labelled "approximate".

Chrome deliberately rounds GPU timestamps to 0.1 ms for privacy. A single frame of 0.3 ms can therefore read as 0.2 or 0.4 ms, but over the hundreds or thousands of frames in a test the rounding averages out.

4. Choosing the scene

The cost of an SPH frame depends heavily on the scene: particle count, how tightly particles are packed, obstacles, rigid particles, streamlines and the renderer. The Scene menu picks what the tests run:

SceneTestsWhat it shows
Dam break (reference)3 particle counts + 3 renderersThe fixed, scaled reference scene described below. Use this one to compare machines.
Chopped fibers stirred tankone per rendererFluid coupled to rigid chopped fibres (DEM) and a stirrer.
Flow streamlines, box containerone per rendererInflow / outflow past an obstacle, with streamline tubes.
Heat exchanger streamlinesone per rendererFlow through an imported mesh container, with streamline tubes.
Vibrating cylinder containerone per rendererA vibrating container with 9 solver substeps per frame.
Current scene (your setup)one per rendererYour own scene exactly as it is when you press Start: how fast your hardware runs your case.

The demo scenes and your own scene run at their own particle count and substeps per frame, which the results show for each test. Their scores are only comparable with runs of the same scene. MPUPS counts fluid particles only, so rigid particles and streamlines make a scene slower per frame without adding to its MPUPS.

The dam break reference is built the same way on every machine:

5. The reference test set

TestParticlesRendererWhat it stresses
Particles Light≈ 50 kParticlesPer-frame overhead: dispatch count, driver and browser cost. Small counts are dominated by fixed costs.
Particles Standard≈ 150 kParticlesA typical working size.
Particles Heavy≈ 400 kParticlesMemory bandwidth and compute throughput of the SPH solver: neighbour search and the density / pressure passes.
Marching Cubes≈ 150 kMarching CubesDensity-volume splatting plus surface extraction.
Screen Space≈ 150 kScreen SpaceDepth and thickness passes, smoothing filters and foam; scales with canvas size.
Raymarch≈ 150 kRaymarchVolume ray-marching through the density texture; the heaviest renderer per pixel.

The exact particle count differs slightly from the target because particles are placed on a regular lattice. The count actually used is shown in the results and exports. The three renderer tests share the same 150 k simulation as Particles Standard, so their differences come from rendering: compare their GPU render times.

6. What happens during a run

  1. Snapshot. Your renderer, all settings, the camera and the play state are saved.
  2. Setup. For each test the renderer is switched if needed, and the reference scene is loaded at the test's particle count. GPU buffers are re-allocated.
  3. Warm-up (3 s, not recorded). The first frames include shader compilation, driver warm-up and the initial collapse of the water column. They are discarded so they do not skew the averages.
  4. Measurement. For the chosen duration, every frame's timing is recorded. Only frames that actually advanced the solver are counted.
  5. Restore. After the last test, or when you press Cancel, your renderer, settings and camera are put back.

The simulation keeps rendering to the screen throughout, exactly as it does in normal use, so the numbers describe the real application and not an artificial loop.

7. Metrics explained

Max FPS
The best sustained uncapped frame rate: the fastest half-second window of the test. A single frame is too noisy to be a fair "maximum", so short bursts are averaged.
Avg FPS
The uncapped frame rate over the whole measurement: 1000 divided by the mean frame time. This is the headline number for a test.
1% low
The frame rate of the slowest 1% of frames (computed from the 99th-percentile frame time). A big gap between Avg and 1% low means stutter: background work, driver hiccups or thermal throttling.
MPUPS
Million Particle Updates Per Second, the particle counterpart of the grid solvers' MLUPS. It counts how many particles the solver advances per second, independent of particle count:
MPUPS = particles × substeps per frame × Avg FPS / 1,000,000
A small scene with high FPS and a large scene with low FPS can reach similar MPUPS; larger scenes usually give higher MPUPS because fixed per-frame costs are spread over more particles.
Peak MPUPS
MPUPS in the best half-second window (in the report and exports).
GPU Sim / GPU Render (ms)
Average GPU time spent on the solver and on drawing, per frame (hover a result row, or see the report). Render time depends on the renderer and your canvas size.
CPU (ms)
Average time the browser's JavaScript spent preparing each frame. If this is close to the frame time, the test is CPU-bound rather than GPU-bound.
Display FPS
How many frames were actually shown on screen per second: at most your monitor's refresh rate. Reported for reference only.

8. The throughput score

The score is the geometric mean of Avg MPUPS over the tests that completed:

Score = (MPUPS₁ × MPUPS₂ × … × MPUPSₙ)^(1/n)

A geometric mean keeps one very fast test from dominating: doubling the speed of any single test raises the score by the same factor, whichever test it is. Because the score depends on which tests were included, compare scores only between runs with the same test selection. The report and exports list the tests used.

9. Getting reliable results

10. Comparing machines

For a fair comparison, use the Dam break (reference) scene and keep the following the same on every machine: the test selection, the duration, the browser, and the window size. The scene is always the same reference scene, so you do not need to reset anything. Then compare Avg FPS and MPUPS test by test, and the score overall.

The browser may hide the exact GPU model for privacy and report only the vendor and architecture (for example "nvidia · ampere"). Note the exact model yourself when you collect results.

11. Reports and exports

ButtonOutputBest for
HTML ReportA self-contained web page: score, system, all metrics per test, FPS-over-time charts and the method notes. Opens in any browser, prints to PDF.Sharing results, archiving a machine's test
CSVOne row per test with every metric.Spreadsheets, collecting many machines
JSONEverything, including system information and the FPS-over-time series.Scripts and databases
CopyA short text summary on the clipboard.Pasting into chat or email

12. Limitations

13. FAQ

Why is Display FPS stuck at 60 when Avg FPS says 250?
Your monitor refreshes 60 times a second, so only 60 frames can be shown. The GPU finishes each frame's work in about 4 ms and then waits; 250 is what it could do without waiting.
Why are Marching Cubes, Screen Space and Raymarch slower than Particles Standard?
They run the same simulation, then do more work to draw it: building a density volume, extracting or ray-marching a surface, or several full-screen passes. The difference is their rendering cost; the GPU Sim time should be about the same.
A test says "no frames measured" or "setup failed".
The GPU could not allocate or run that configuration, most often Particles Heavy on a GPU with too little memory. Untick it and run again.
Does the benchmark change my scene?
Only temporarily. It restores your renderer, settings, camera and play state when it finishes or is cancelled. The simulation restarts from its initial state, a playback recording is cleared, and the undo history starts fresh, as after loading any scene.
Why is my score different from yesterday?
Check the power source, other running programs, window size and browser version. Thermal state matters too: a GPU that is already hot runs slower.