The Bench tab runs real 2D and 3D fluid simulations on your GPU and measures how fast your hardware can actually drive them, 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
Open the Bench tab in the left sidebar.
Choose a Duration per test. 5 s is a quick check, 20 s is a good default for comparable results, and 60 s or more shows thermal throttling on laptops.
Pick a Test set: the Standard suite (fixed tests, best for comparing machines) or any demo scene run at Light / Standard / Heavy / Extreme.
Tick the tests you want. The estimate under the list shows the total run time.
Press Start and keep the browser tab visible until it finishes.
Read the results table and score, then save them with HTML Report, CSV, JSON or Copy.
Your own scene is saved before the run and restored afterwards. The benchmark only changes the grid size, solver engine, 2D/3D view and play state; your obstacles, colours and every other setting stay as they were.
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 2,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:
t0 is written before any simulation work of the frame.
t1 is written after the last solver substep, before rendering starts.
t2 is written after the frame has been drawn.
Because the simulation 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 and the Performance folder show 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. The test set
Each test runs one solver at one grid size. Tests are grouped from light to heavy so a range of hardware, from integrated laptop graphics to desktop GPUs, lands somewhere meaningful.
Test
Grid
Cells
Default
What it stresses
2D Light
640×360
0.23 M
on
Per-frame overhead: dispatch count, driver and browser cost. Small grids are dominated by fixed costs, not memory bandwidth.
2D Standard
1280×720
0.92 M
on
A typical working resolution.
2D Heavy
2560×1440
3.7 M
on
Memory bandwidth and compute throughput of the incompressible solver.
2D Compressible
1280×720
0.92 M
on
The explicit compressible (Euler/HLLC) solver, which uses 32-bit state and more arithmetic per cell. Runs the scene's Solver Steps/Frame (default 4) each frame.
3D Light
64³
0.26 M
on
3D solver plus volume ray-marching at a light grid.
3D Standard
128³
2.1 M
on
A typical 3D working resolution; 3D texture bandwidth.
3D Heavy
256³
16.8 M
off
Large-memory, high-bandwidth GPUs. Needs several GB of free video memory; can fail or stall on smaller or integrated GPUs.
3D Compressible
64³
0.26 M
off
The 3D compressible solver, which runs 8 substeps per frame. Its pipelines compile on first use, which adds a one-time wait.
The tests use your current scene's obstacles and physical settings; only the grid size and engine are swapped. For results that are strictly comparable between machines, run the benchmark on the same scene: the default scene after Reset All Settings is the reference.
4b. Demo scenes as test sets
Besides the Standard suite, the Test set menu lists every demo scene bundled with the app (the same ones as the Demo tab). Choosing one benchmarks that real scene: its obstacles, painted shapes, meshes, physics options and view settings, at up to four sizes.
Tier
2D demos
3D demos
Default
Light
½ × grid
½ × resolution
on
Standard
as authored
as authored
on
Heavy
2 × grid
2 × resolution
on
Extreme
3 × grid
4 × resolution
off
Standard is the scene exactly as saved; the other tiers scale its grid in both directions, keeping the aspect ratio. 2D grids are rounded to a multiple of 8.
3D resolution is capped at 256³. A tier that would land on the same grid as another is shown greyed out ("same grid as …") and skipped, for example Heavy and Extreme on a demo already authored at 256³.
Painted 2D shapes are redrawn at each size, so every tier runs the same geometry.
The demo is loaded only for the run. Your whole scene (settings, painted shapes, background image, imported mesh) is saved first and put back afterwards, and your light/dark theme is kept throughout.
Results, reports and exports name the test set (for example "Demo: Propeller"). Compare scores only between runs of the same test set.
Use the Standard suite to compare hardware, and demo sets to answer "how fast will this kind of simulation run on this machine?".
5. What happens during a run
Snapshot. The current view (2D/3D), grid sizes, engines and play state are saved.
Setup. For each test the solver is switched to the test's grid and engine, and its GPU memory is re-allocated. If the solver's GPU programs are not compiled yet, the run waits for them (up to 2 minutes).
Warm-up (3 s, not recorded). The first frames after a re-allocation include driver warm-up and a freshly started flow. They are discarded so they do not drag the averages down.
Measurement. For the chosen duration, every frame's timing is recorded. Only frames that actually advanced the solver are counted.
Restore. After the last test, or when you press Cancel, your scene is 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.
6. 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.
MLUPS
Million Lattice (grid-cell) Updates Per Second, the standard way to compare CFD solver speed across hardware. It counts how many grid cells the solver advances per second, independent of grid size:
A small grid with high FPS and a large grid with low FPS can reach similar MLUPS; larger grids usually give higher MLUPS because fixed per-frame costs are spread over more cells.
Peak MLUPS
MLUPS 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 your canvas size, not the grid.
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.
7. The throughput score
The score is the geometric mean of Avg MLUPS over the tests that completed:
Score = (MLUPS₁ × MLUPS₂ × … × MLUPSₙ)^(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.
8. Live readouts in Performance
The same timer runs all the time, so the Performance folder in both the 2D and 3D menus shows live, uncapped numbers for whatever scene you are running:
Readout
Meaning
Uncapped FPS (real)
What this scene would run at without the monitor cap, averaged over 0.5 s.
Display FPS (vsync)
Frames actually shown per second (capped by the monitor).
Display Frame (ms)
Time between shown frames.
GPU Sim (ms) / GPU Render (ms)
GPU time per frame for the solver and for drawing.
CPU Frame (ms)
JavaScript time per frame.
MLUPS (M cells/s)
Solver throughput; 0 while paused.
Timing Source
GPU timestamps, or the approximate fallback.
These are useful for tuning a scene: raise the grid or iteration count and watch Uncapped FPS and GPU Sim respond, even while the display stays at 60.
9. Getting reliable results
Keep the tab visible. Browsers pause hidden tabs; the status line warns you if the tab was hidden during a test.
Plug laptops in and use a high-performance power plan. On battery, GPUs often run at a fraction of their speed.
Use the discrete GPU. On laptops with two GPUs, make sure the browser runs on the dedicated one (Windows: Settings → Display → Graphics).
Close other GPU work: games, video calls, other WebGPU or 3D tabs, screen recorders.
Keep the window size fixed between runs. Rendering cost grows with the canvas size, which the report records.
Use longer runs for laptops. 60 s or more reveals thermal throttling as a falling FPS line in the HTML report.
Run twice. Differences under about 3–5% between runs are normal noise.
10. Comparing machines
For a fair comparison, keep the following the same on every machine: the scene (use Reset All Settings), the test selection, the duration, the browser, and the window size. Then compare Avg FPS and MLUPS 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
Button
Output
Best for
HTML Report
A 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
CSV
One row per test with every metric, including the test set.
Spreadsheets, collecting many machines
JSON
Everything, including system information and the FPS-over-time series.
Scripts and databases
Copy
A short text summary on the clipboard.
Pasting into chat or email
12. Limitations
Browser overhead is included. This measures the real application in a browser; a native solver on the same GPU would be faster.
2D has a fixed cost per frame. Small 2D grids are limited by per-frame overhead (a few milliseconds) rather than by grid size, so 2D Light does not reach thousands of FPS on most GPUs. The larger tests are the better measure of raw GPU throughput.
Timestamp rounding. 0.1 ms rounding in Chrome limits precision for frames under about 1 ms; averages remain accurate.
Power management. GPUs change clock speeds with load and temperature. The warm-up reduces this effect but does not remove it.
Scene dependence. Obstacles, particles, view mode and physics options change the cost per frame. Use the same scene when comparing.
13. FAQ
Why is Display FPS stuck at 60 when Uncapped 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 does 2D Compressible get a higher FPS than 2D Incompressible at the same grid?
FPS measures the cost of one frame, not how fast the flow evolves. The incompressible solver must solve a pressure equation every step: about 40 Jacobi iterations, each a full pass over the grid, so roughly 50 GPU passes per step. The compressible solver is explicit: two Runge-Kutta stages and no pressure solve, only about 2–3 passes per step. It runs 4 steps per frame by default (Solver Steps/Frame in the Compressible folder), which the MLUPS figure accounts for. Each compressible step is therefore much cheaper, but explicit solvers must take much smaller time steps (limited by the speed of sound), so they need many more steps to simulate the same physical time. Higher FPS here does not mean the compressible case is the lighter simulation overall.
A test says "no frames measured" or "setup failed".
The GPU could not allocate or run that configuration, most often 3D Heavy on a GPU with too little memory. Untick it and run again.
The browser froze or the GPU reset during 3D Heavy.
The GPU took too long on a frame and the operating system reset it. Reload the page and leave 3D Heavy off on that machine.
Does the benchmark change my scene?
Only temporarily. It restores the view, grid sizes, engines and play state when it finishes or is cancelled. The flow itself restarts, as it does whenever the grid changes.
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.