WAB compression — what wab_compression costs and buys

wab_compression defaults to "none". Turning it on trades CPU on the ack path — which is inside the Durable latency a producer waits for — against bytes on disk, which decides how much burst the buffer holds and how long it survives an outage. Until now neither side had a number.

The verdict inverts with record size, and it inverts hard. At ~150-byte records zstd is a bad trade. At ~4 KiB it is free on fast storage and a net throughput win on slow storage.

Measured

20,000 Durable records per cell, batch_size = 256, via push_batch. beast — i9-9900K, ext4 on a Samsung 850 EVO SATA SSD, honest fdatasync:

recordcodecrec/svs. nonecompression ratio
149 Bnone92,8251.00x1.00
149 Bzstd level 167,0570.72x1.15
149 Bzstd level 374,5410.80x1.12
149 Bzstd level 958,5730.63x1.12
4,011 Bnone36,8371.00x1.00
4,011 Bzstd level 147,5831.29x29.16
4,011 Bzstd level 346,6301.27x28.93
4,011 Bzstd level 941,8721.14x28.93

The same sweep on an M3 Max (APFS on NVMe, F_BARRIERFSYNC — a much cheaper flush) for contrast:

recordcodecrec/svs. none
149 Bnone137,1071.00x
149 Bzstd level 156,2840.41x
4,011 Bnone25,6981.00x
4,011 Bzstd level 125,6741.00x

Why compression can make weir faster

At 4 KiB, zstd level 1 turns each record into ~137 bytes. That is ~29x less to write and ~29x less for the flush to push through. On beast the CPU spent compressing is more than repaid by the I/O saved, so enabling compression raises throughput by 29% — and even level 9, which costs six times the CPU of level 1, still beats no compression by 14%.

On the M3 Max the same compression buys the same ratio but only breaks even, because that platform's flush was never the bottleneck. The slower the storage, the more compression wins — which is the opposite of the usual intuition that compression is a space-for-time trade.

At 149 bytes there is nothing for the codec to work with: ~15% smaller for 28–37% less throughput on beast, and 59% less on the Mac. Higher levels make it strictly worse, and at that size level 3 compressed better than level 9 while level 1 beat both — the levels stop being ordered when the input is too small to matter.

Read the two columns differently

The throughput column transfers. The ratio column does not.

Throughput measures CPU per byte against I/O saved; it does not care what the bytes are, so the shape above will hold for your data.

The ratio is only as honest as the corpus, and this corpus is not honest: the 4 KiB record is 27 copies of one JSON log line, which is why it reports 29x. Real 4 KiB records — distinct log lines, JSON with varying fields, anything already encoded — will report low single digits. Treat 29x as an upper bound that says "the codec worked", not as a number to size a disk with.

Measure your own: weir exposes both halves already, so the live ratio on real traffic is

weir_wab_record_logical_bytes_total / weir_wab_record_stored_bytes_total

Guidance

your recordsrecommendation
under ~1 KiBleave wab_compression = "none". The ratio is ~1.1x and it costs a quarter to a half of ingest throughput.
~4 KiB and above, slow storageturn on zstd at level 1. It paid for itself and then some on a SATA SSD.
~4 KiB and above, fast storage (NVMe)level 1 is roughly free; enable it for the space, not the speed.
any sizelevel 1. Higher levels cost real throughput and bought nothing measurable here.

Reproducing

cargo test -p weir-server --test research --release -- --ignored --nocapture \
  --test-threads=1 compression_cost_and_benefit

Edit REPEATS in that test to match your own record sizes; the default sweeps one line (~149 B) and 27 lines (~4 KiB).