OPFS sync write benchmark

2026-09-16T05:10:12.315Z · AMD Ryzen 7 7800X3D 8-Core Processor (16 threads), 65 GB, linux 7.0.0-31-generic x64

Config: preset=quick+overrides, N=2000, S=4096 B, chunks=64 KiB / 1 MiB, R=1, M=200 · Profiles on: ext4 (/)

Experiment, not a cross-browser comparison.

Per-file cost

Workload 5. Each step of create+open, first write, close and delete timed on its own, per file, plus the full cycle. Populating a file system pays the first three per file. Mean time per call in the median run, log scale; the distance between the marks is the ratio between browsers, printed on the right. Hover a mark for p50 and p99.

Firefox 158
100 µs1 ms10 ms100 ms1000 msnew-file: create+openFirefox 158 — new-file: create+open: mean 48.6 ms/call, p50 48.0 ms, p99 56.3 ms, total 9.7 sFirefox 158 — new-file: create+open: mean 48.6 ms/call, p50 48.0 ms, p99 56.3 ms, total 9.7 snew-file: first writeFirefox 158 — new-file: first write: mean 614 µs/call, p50 580 µs, p99 940 µs, total 122.7 msFirefox 158 — new-file: first write: mean 614 µs/call, p50 580 µs, p99 940 µs, total 122.7 msnew-file: closeFirefox 158 — new-file: close: mean 31.6 ms/call, p50 31.3 ms, p99 35.1 ms, total 6.3 sFirefox 158 — new-file: close: mean 31.6 ms/call, p50 31.3 ms, p99 35.1 ms, total 6.3 snew-file: deleteFirefox 158 — new-file: delete: mean 32.3 ms/call, p50 31.7 ms, p99 38.2 ms, total 6.5 sFirefox 158 — new-file: delete: mean 32.3 ms/call, p50 31.7 ms, p99 38.2 ms, total 6.5 snew-file: full cycleFirefox 158 — new-file: full cycle: mean 113.1 ms/call, p50 111.7 ms, p99 122.6 ms, total 22.6 sFirefox 158 — new-file: full cycle: mean 113.1 ms/call, p50 111.7 ms, p99 122.6 ms, total 22.6 s
WorkloadFirefox 158 µs/callp50 / p99 (µs)total
new-file: create+open
getFileHandle({create: true}) + createSyncAccessHandle() on a name that does not exist yet
48.6 ms47960 / 562809.7 s
new-file: first write
first write(4096 B, {at: 0}) into the empty file
614 µs580 / 940122.7 ms
new-file: close
close() on the access handle
31.6 ms31280 / 350606.3 s
new-file: delete
removeEntry(name)
32.3 ms31740 / 382406.5 s
new-file: full cycle
create+open → write 4096 B → close → delete, per file
113.1 ms111660 / 12260022.6 s

Durability syscalls per call (strace)

fsync,fdatasync,syncfs,sync_file_range counted by strace and attributed to each pass's timed loop by wall-clock window; "per call" divides by calls × passes, warm-up included. "Outside the loop" is the per-pass file creation and deletion that workloads 1–4 do around their timed loop; new-file times those steps inside the loop.

WorkloadFirefox 158 syncs/callms in sync/calloutside loop, per pass
new-file21107.290.00

Firefox 158: 8862 calls, 46.2 s inside them, 421 outside any workload. Most-synced files:

Environment

BrowserVersionModeProfile onperformance.now() stepIsolatedExecutableUser agent
Firefox 158firefox/158.0a1headless, straceext4 (/)20 µsyes/home/theo/dev/firefox/obj-opt/dist/bin/firefoxMozilla/5.0 (X11; Linux x86_64; rv:158.0) Gecko/20100101 Firefox/158.0
Firefox 158: Bugzilla summary
**OPFS `FileSystemSyncAccessHandle.write()` per-call overhead benchmark**

Environment:
- User agent: `Mozilla/5.0 (X11; Linux x86_64; rv:158.0) Gecko/20100101 Firefox/158.0`
- Platform: Linux x86_64; hardwareConcurrency: 16
- Timestamp: 2026-09-16T05:10:12.315Z
- performance.now() resolution in the worker: 20 µs (crossOriginIsolated: true)
- navigator.storage.estimate(): 0.5 MB used of 10737 MB
- Config: preset=quick+overrides, N=2000, S=4096 B, chunks=64 KiB / 1 MiB, R=1, M=200

Median run of R=1 (by total time) after one warm-up pass; latency percentiles are per call; "1st call" is call number 1 of that run (for the append workloads, the first write into the freshly created file):

| Workload | Calls | Bytes/call | Total (ms) | Total min–max (ms) | ops/s | MB/s | p50 (µs) | p90 (µs) | p99 (µs) | max (µs) | 1st call (µs) |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| new-file: create+open | 200 | – | 9729.5 | 9729.5–9729.5 | 21 | – | 47960.0 | 50880.0 | 56280.0 | 90540.0 | 52980.0 |
| new-file: first write | 200 | 4,096 | 122.7 | 122.7–122.7 | 1,629 | 6.7 | 580.0 | 660.0 | 940.0 | 3320.0 | 600.0 |
| new-file: close | 200 | – | 6321.0 | 6321.0–6321.0 | 32 | – | 31280.0 | 32680.0 | 35060.0 | 35460.0 | 35460.0 |
| new-file: delete | 200 | – | 6454.3 | 6454.3–6454.3 | 31 | – | 31740.0 | 33560.0 | 38240.0 | 41260.0 | 33560.0 |
| new-file: full cycle | 200 | 4,096 | 22628.2 | 22628.2–22628.2 | 9 | 0.0 | 111660.0 | 117840.0 | 122600.0 | 156640.0 | 122600.0 |

Derived:
- new-file: 113.1 ms per file (9 files/s) = create+open 48.6 + first write 0.6 + close 31.6 + delete 32.3 ms
- new-file without delete (what populating OPFS pays per file): 80.9 ms