I backed up an SD card from a ResMed AirSense 10 last week: three and a half years of sleep data, 1.6 GB of EDF files. Before copying it anywhere I wanted to compress it, good excuse to benchmark instead of defaulting to whatever I usually reach for.

My usual default is 7z + LZMA2. For sharing files with non-technical people, plain zip. I don’t really question it.

This experiment changed how I think about at least one of those defaults.

ResMed stores everything in EDF (European Data Format), a standard from 1992 for storing continuous biological signals. Each night produces a handful of files:

  • BRP.edf: raw breathing flow and pressure, 25 samples per second (~1.7 MB/night)
  • PLD.edf: slower stats every 2 seconds (leak rate, respiratory rate, tidal volume)
  • SAD.edf: SpO2 and pulse
  • EVE.edf: timestamped respiratory events: apneas, hypopneas
  • STR.edf: long-term summary across all nights

1,039 nights total. The bulk of the size is in the BRP files.

The benchmark

I tested everything I had installed or could install quickly: gzip, bzip2, bzip3, xz, lzma, zstd, brotli, lrzip, zpaq, lz4, lzop, and 7z. I ran it across five nights spanning 2024–2026, then also on all five combined.

ToolSavedCompress time
bzip379%0.1–0.2s/night
zpaq -m378%0.5s/night
bzip2 -975%0.1s/night
lrzip -b75%0.2s/night
xz -971%0.5–0.8s/night
lzma -971%0.5s/night
7z (lzma2)71%1.0s/night
brotli -q1168%2.8s/night
zstd -1967%0.4–0.7s/night
gzip -957%0.2s/night
lz4 -952%0.1s/night

The results were consistent across every night. EDF data compresses predictably. Benchmark run on a MacBook Pro M1, 16 GB RAM.

Why bzip2 beats LZMA-style compression here

This was the surprising part. LZMA2 is usually my boringly good default. Here it landed at 71%, while bzip2 hit 75% and bzip3 reached 79%.

EDF files are 16-bit signed integers sampled at fixed intervals. Breathing flow and pressure change slowly and smoothly. On this dataset, bzip2 beat the LZMA-style tools by four points. Not what I expected.

My best guess at why: bzip2’s Burrows-Wheeler Transform handles repetitive byte patterns well, and slowly-varying biosignals produce a lot of those. LZMA-style compressors, including LZMA2, use dictionary matching and range coding, which usually do well on mixed or text-heavy data. I can’t say for certain that’s the reason, but it fits.

bzip3, written by Kamila Szewczyk in 2022, extends BWT with improved algorithms and took the top spot on every night tested.

What OSCAR uses internally

OSCAR is the de facto open source tool for viewing CPAP data, used by patients to analyze ResMed, Philips Respironics, and Fisher & Paykel machines. If you have a CPAP and want to review your own data outside of the manufacturer’s app, OSCAR is where most people land.

I pointed amp’s agent CLI at the CrimsonNape fork, the latest OSCAR from sleepfiles.com/OSCAR, and asked what compression it uses. Three places, all DEFLATE via zlib, but each does it differently. Session event data in .001 files goes through Qt’s qCompress() in session.cpp, which tacks on a 4-byte size header. Machine summaries use a homegrown gCompress() wrapper in common.cpp that strips Qt’s headers and rebuilds a gzip stream. And for ResMed SD card backups, it just calls gzopen/gzwrite directly in resmed_EDFinfo.cpp.

gzip/DEFLATE is the ~57% row in the benchmark table. OSCAR’s internal format is less compact than archiving the raw EDF files yourself with bzip2. That makes sense since DEFLATE is fast and built into Qt, but it means the OSCAR data directory ends up roughly the same size as the original SD card data. The raw EDF files compressed with bzip2 are smaller than OSCAR’s imported copy, and they’re the source of truth OSCAR reads from anyway.

bzip3 has the best numbers. So why not bzip3? For medical data, long-term compatibility carries real weight.

bzip2 has been around since 1996. tar -xjf works broadly on Unix-like systems without installing anything, 7zip opens it, any Linux machine opens it. The format isn’t going anywhere.

bzip3 is a 2022 project by one person. It’s not in standard tar. It’s not pre-installed anywhere. Great tool, wrong choice for a long-term medical archive.

I generally default to 7z + LZMA2 for archival. Works fine on mixed data and is fast enough. But sometimes, when the data has structure and the files are large enough, it’s worth benchmarking.

tar -cjf ResMed_CPAP.tar.bz2 ResMed_CPAP/

1.6 GB to 407 MB. 1 minute 33 seconds. 75% smaller.