Benchmarks
mdtest
sandbox.exec in a LayerFS v1.0.0 Workspace, on a FUSE baseline (libfuse’s passthrough_ll), and on the kernel's own overlayfs, one after the other.
LayerFS against FUSE baseline
vs FUSE baseline- LayerFS
- core at main e5c7aaae05, through the JS SDK
- Tool
- IOR mdtest f1172add · Open MPI 4.1.4, 1 and 4 procs
- Baseline
- libfuse passthrough_ll 3.14.0, a sibling container on the same VM
- Reference
- kernel overlayfs, the same Sandbox's own /tmp (no FUSE)
- Host
- arm64 Mac · Docker Desktop, linux/arm64, 8 CPUs, 8.3 GB
- Load
- 7.9–15.7 (1 min), three-arm run
Completeness and the Commit
9 / 9 exit 0
every case, 1 and 4 MPI processes; the FUSE baseline finished 7 of 9, 2 reached the 115 s ceiling
2.6 s
130 µs per file, mountable as a Commit
Against a FUSE baseline
The like-for-like comparison: libfuse’s passthrough_ll (fuse-3.14.0) over a plain directory, writeback off, same mpirun command, same run. LayerFS records every change for the next Commit as it goes.
create, rename, remove · 1 process
0.86–1.28×
on par with the baseline
create, rename, remove · 4 processes
1.21–4.22×
ahead in every phase both finished
stat and open/close
2.94×–784×
a cache setting, not daemon speed (below)
LayerFS ÷ FUSE baseline in each cell, then both ops/s (LayerFS / baseline). Above 1× LayerFS is faster; within 15 % shown as on par. "unique" gives each process its own directory.
What the comparison says
One process: on par
Create, rename and remove run at 0.86–1.28× of the baseline, while LayerFS also records each change. It trails in 4 of those 10 phases (removal, and creating directories in one shared directory), by up to 14 %.
Four processes: ahead
With four processes LayerFS is 1.21–4.22× the baseline in every write phase both finished. The baseline gets slower with four processes; with a directory each, LayerFS does (11,597 file creates/s against 4,143 for one).
Stat and open/close are a cache setting
LayerFS answers with a 60 s entry and attribute timeout, so the kernel serves repeat stats from cache. passthrough_ll keeps its default 1.0 s timeout, so its stats reach the daemon. That lead is a setting, not daemon speed.
Two cases the baseline did not finish
With four processes making directories, passthrough_ll reached the 115 s ceiling; LayerFS finished both. They are left out of the ranges above.
The reference is not like-for-like
Kernel overlayfs is the Sandbox's own overlayfs /tmp: the kernel's in-memory path, no FUSE. It is the ceiling for this host, not a peer:
No FUSE hop
The reference runs inside the kernel. Every LayerFS operation is a FUSE request to its daemon, a round trip every FUSE filesystem pays.
Writes reach the daemon
Kernel writeback caching is off under the FUSE contract, so each buffered write reaches LayerFS; the reference only copies into page cache.
Every change is recorded
LayerFS records each change so a Commit can capture it and mount it again later. The reference keeps nothing once the container goes.
A ceiling, not a peer
Ratios show the cost of those properties against the fastest local path on this host. The like-for-like comparison is the FUSE baseline, libfuse’s passthrough_ll, measured in the same run.
LayerFS ÷ kernel overlayfs, phase by phase
mdtest's own ops/s as recorded; each cell shows LayerFS ÷ kernel overlayfs, then LayerFS / FUSE baseline / kernel overlayfs. In the write phases the baseline sits about as far below the kernel path as LayerFS, or further: most of the gap is the FUSE round trip itself. Stat is at or above the kernel path in 8 of 10.
Read with care
A sibling container
A Sandbox cannot host a second FUSE mount (no-new-privileges, no user namespaces), so passthrough_ll runs in a sibling container from the same image, on the same VM and kernel; the tool runs as the same uid 501.
Its own defaults
passthrough_ll runs as root with no credential switch, up to 10 threads and a 1.0 s cache timeout. It keeps nothing beyond the directory: no recording, no Commit.
It slows with size
passthrough_ll finds inodes in one mutex-guarded list, so it slows as the file count grows; each case holds 20,000 items per process. An indexed server (passthrough_hp) was not measured.
Empty files
mdtest writes nothing (-w 0 -e 0), so read is an open and close. Data rates are on the fio page.
One sample each
One run per case and arm, host load 7.9–15.7 (1 min). Cache state warm/unknown, not cold. An earlier two-arm run is in the data folder.
This host
Docker Desktop on an arm64 Mac, LayerFS at main e5c7aaae05, mdtest from IOR f1172add, Open MPI 4.1.4, Disposable Store.
Data: benchmark/data/mdtest/v1.0.0/three-arm/ in the LayerFS repository (every phase, the Commit, environment, receipts and the run record).