Skip to content

Benchmark Report — Batched Cross-Inode Flush

2026-08-27

Summary

Service.flushEntries publishes several inodes' buffered extents in one etcd transaction rather than one transaction each. It had been in the tree, correct, and unmeasured: the small-file storm cannot exercise it, because close() publishes each file before the interval sweep ever sees it. This scenario is the workload it was written for — many files open at once on every node, written to continuously and never closed, so the sweep is what publishes them (scripts/bench/compare/bench-batched-flush.sh).

The measurement is direct rather than inferred: etcfuse_metadata_flush_batch_total counts the transactions and etcfuse_metadata_flush_batch_inodes_total the inodes they carried, sampled either side of the run.

Result

3-node cluster on m5.large, 256 files held open per node, 300 seconds of writing.

Metric Value
batched flush transactions 60
inodes published by them 2428
inodes per transaction 40.5

A commit is the unit of cost in this filesystem, so 40.5 inodes per commit is the same publication work at one fortieth of the consensus cost. The batch cap is 64 inodes per transaction, so the sweep is running close to it: the buffers are genuinely arriving faster than the interval, which is the condition the batch exists for.

This answers the open question about the mechanism — it pays for itself where it applies, and it stays. It remains irrelevant to the small-file storm for the structural reason above, and no storm number should be attributed to it.