Benchmarks

fsx

xfstests' file exerciser: one file, a seeded random stream of reads, writes, mapped I/O, truncates and range operations, and after every step a byte-for-byte check against its own model of what the file must hold. We run it through sandbox.exec inside a LayerFS v1.0.0 Workspace, and the same commands on the kernel's own overlayfs as the reference.

LayerFS against kernel overlayfs

vs kernel overlayfs
KindCorrectnessdata integrityindustry standard
LayerFSv1.0.0
Ran on
LayerFS
core at main e5c7aaae05, through the JS SDK
Tool
xfstests ltp/fsx at 22348afe338c
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.5–14.9 (1 min)

Verdict

LayerFS v1.0.0

14 / 14 PASS

3.06 M operations checked · 0 data or size miscompares

files from 256 KiB to 64 MiB · mapped, buffered and direct I/O

Kernel overlayfs (reference)

14 / 14 PASS

same commands, same Sandbox, the container's overlayfs /tmp

Every variant, both seeds

Seven fsx configurations, seeds 1 and 2, each run once per arm. PASS is fsx's own "All operations completed A-OK" with exit 0.

Variantfsx argsOps per armLayerFSKernel overlayfs
default(none)600,000PASSPASSPASSPASS
no-mmap-R -W600,000PASSPASSPASSPASS
aligned-r 4096 -w 4096 -t 4096600,000PASSPASSPASSPASS
medium-l 4194304400,000PASSPASSPASSPASS
large-l 67108864 -o 104857624,000PASSPASSPASSPASS
large-no-mmap-l 67108864 -o 1048576 -R -W32,000PASSPASSPASSPASS
direct-Z -R -W -r 4096 -w 4096800,000PASSPASSPASSPASS

What fsx could exercise

fsx probes optional operations at start and turns off any the filesystem refuses. Reads, writes, mapped reads and writes, truncates and direct I/O ran on both arms. These are the optional ones:

Outside LayerFS's FUSE surface, by design

No extended attributes, fallocate, ioctl, copy_file_range, locks or lseek; the kernel falls back or returns EOPNOTSUPP. Left unimplemented on purpose: no FUSE capability for them is requested. So fsx turned these off on LayerFS. layerfs-fuse/src/operations/unsupported.rs

  • fallocate(0)
  • fallocate(KEEP_SIZE)
  • fallocate(PUNCH_HOLE|KEEP_SIZE)
  • fallocate(ZERO_RANGE)
  • fallocate(COLLAPSE_RANGE)
  • fallocate(INSERT_RANGE)

Refused on both

The container's overlayfs refuses these too, so they say nothing about LayerFS.

  • fallocate(UNSHARE_RANGE)
  • fallocate(WRITE_ZEROES)
  • clone range
  • dedupe range
  • exchange range
  • dontcache IO
  • atomic writes (needs -Z)
  • atomic writes (IO stack)

Since the v0.1.6 report

Issue #361 reported FUSE failures on v0.1.6. fsx shows where v1.0.0 stands on each.

v0.1.6 (#361)v1.0.0
Writes past 1 MiBcp and dd failed with EINVAL✓ files grew to 4 MiB and 64 MiB, every byte checked
Mapped writesmmap writes failed with EINVAL✓ fsx default mix (mapped reads and writes) passes
O_DIRECTnot reported✓ 800,000 direct-I/O ops pass
fallocateOperation not supported– not served, by design (no FUSE fallocate capability is requested)

How it ran

Only through the JS SDK

Every fsx run is a sandbox.exec as the Sandbox's user (501), in the mounted Workspace and then in /tmp of the same container.

  1. project.init(a seed folder)the Store
  2. sandbox.create("bench", image)fsx built in, pinned by digest
  3. branch.fork("bench", "main")its own Branch
  4. sandbox.mount("bench", "bench")/workspaces/1
  5. sandbox.exec(× 28 + read-back)one fsx run each
  6. sandbox.commit(after all cases)everything fsx left
  7. sandbox.unmount(…, then close)

Then a Commit

After all 14 LayerFS runs, one sandbox.commit captured every file fsx left behind.

457 ms

166.7 MB logical · 15.3 MB newly stored

Speed, indicative only

fsx is a correctness tool; its pace is incidental. ops/s is Σ ops ÷ Σ fsx wall time over both seeds, one sample each on a loaded host.

VariantLayerFS ops/sKernel overlayfs ops/s
default8,5918,515
no-mmap9,69021,750
aligned11,71310,650
medium7,3758,090
large1,1522,036
large-no-mmap1,3012,438
direct12,8879,178

Read with care

  • One sample each

    Each variant, seed and arm ran once. Host load was 7.45-14.87 (1 min); seeds on one arm differ as much as some arm pairs.

  • Not exercised

    fsx’s AIO, io_uring and log-writes modes were not run; fallocate ops were off on LayerFS, which does not serve them by design.

  • Warm caches

    fsx reads what it just wrote. Nothing here is a cold read.

  • This host

    Docker Desktop on an arm64 Mac, LayerFS at main e5c7aaae05, Disposable Store. Not a native Linux qualification.

Data: benchmark/data/fsx/v1.0.0/ in the LayerFS repository (results, environment, raw receipts and the run record).