Skip to content

Zarr codecs

Measured on 2026-11-09 with dspk 0.0.8, on NVIDIA GeForce RTX 2070 with Max-Q Design · Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz (12 threads) · Linux 7.2.15-300.fc45.x86_64.

10 s of 384 Neuropixels channels, float32 in µV, default chunking, the median of 3 runs. Reads come from the page cache (the store was just written), so they measure decompression and not the disk. The machine was also running the app. Every store read back exactly what was written.

Codec Size (MiB) Ratio Write (s) Read (s)
none 439 1.00 3.5 0.73
zstd 1 112 3.94 3.0 0.87
zstd 3 (default) 108 4.07 3.5 0.94
zstd 3, one thread 108 4.07 4.7 0.80
zstd 9 101 4.36 5.8 0.83
blosc_lz4 236 1.86 2.9 0.71
Codec Size (MiB) Ratio Write (s) Read (s)
none 439 1.00 3.3 0.68
zstd 1 407 1.08 2.8 0.70
zstd 3 (default) 408 1.08 3.2 0.67
zstd 3, one thread 408 1.08 3.8 0.71
zstd 9 407 1.08 3.2 0.70
blosc_lz4 403 1.09 2.9 0.81
  • Raw recordings compress well; filtered ones barely do. A raw recording is integer steps scaled to µV, so its float32 values repeat. A filter turns them into full-precision floats, whose low bits look random to every codec here.
  • On filtered data the codec hardly matters. Every codec saves 7 to 8% in about the same time, so the default costs nothing.
  • zstd level 3 is the default because on raw data it nearly matches level 9’s size at about half the write time.
  • parallel matters most where compression does the work. Chunks are compressed on separate threads, which is why several chunks per processing window speed up writing; on raw data one thread is clearly slower.
Terminal window
uv run python benchmarks/signal-operations/zarr_codecs.py