--clumpify multi-data-type benchmark
Generated 2026-05-06. Branch clumping @ 3fd0454,
--cores 6 --memory 1G (default) on a 16 GiB Apple M1 Pro.
Three configurations per dataset (plus a pending fourth):
--clumpify: reorder + default gzip level 1--compression 6: gzip level 6, no reordering — gzip-only win--clumpify --compression 6: both — combined winscrnaseq_10x_clumpify_compress6
row is still running at the time this report was generated. Placeholder
values are marked TBD; numbers will be filled
in when the run completes (estimated finish 23:00–23:15).
| Dataset | Mode | Configuration | Wall (s) | User CPU (s) | Max RSS | Output (MB) | Saving vs plain | Wall vs plain |
|---|---|---|---|---|---|---|---|---|
| MiSeq amplicon (CRISPR) | SE 4.4M | plain | 16.1 | 87.8 | 114 MB | 500 | — | 1.00× |
| --clumpify | 16.4 | 89.3 | 1265 MB | 418 | −16.3% | 1.02× | ||
| --compression 6 | 26.4 | 144.6 | 114 MB | 374 | −25.1% | 1.64× | ||
| --clumpify --compression 6 | 24.2 | 129.5 | 1274 MB | 342 | −31.7% | 1.51× | ||
| ChIP-seq | SE 28.6M | plain | 12.9 | 82.9 | 71 MB | 1542 | — | 1.00× |
| --clumpify | 18.1 | 104.7 | 1495 MB | 1543 | +0.08% | 1.40× | ||
| --compression 6 | 63.4 | 378.3 | 72 MB | 1325 | −14.1% | 4.91× | ||
| --clumpify --compression 6 | 61.6 | 329.3 | 1230 MB | 1308 | −15.2% | 4.77× | ||
| WES | SE 105M | plain | 102.3 | 637.1 | 88 MB | 9166 | — | 1.00× |
| --clumpify | 113.7 | 777.9 | 1856 MB | 8758 | −4.4% | 1.11× | ||
| --compression 6 | 652.2 | 3809.2 | 80 MB | 7756 | −15.4% | 6.38× | ||
| --clumpify --compression 6 | 636.7 | 3552.8 | 1304 MB | 7285 | −20.5% | 6.22× | ||
| Long-read (ONT/PacBio) | SE ~100K | plain | 10.1 | 32.1 | 867 MB | 558 | — | 1.00× |
| --clumpify | 10.8 | 36.1 | 781 MB | 558 | ~0% | 1.07× | ||
| --compression 6 | 33.3 | 157.2 | 974 MB | 510 | −8.6% | 3.30× | ||
| --clumpify --compression 6 | 31.4 | 158.8 | 972 MB | 509 | −8.8% | 3.11× | ||
| ATAC-seq | PE 31.5M | plain | 41.5 | 260.7 | 193 MB | 2869 | — | 1.00× |
| --clumpify | 47.1 | 303.1 | 1654 MB | 1870 | −34.8% | 1.13× | ||
| --compression 6 | 172.1 | 1023.8 | 144 MB | 2247 | −21.7% | 4.15× | ||
| --clumpify --compression 6 | 98.4 | 616.3 | 1989 MB | 1478 | −48.5% | 2.37× | ||
| Ribo-seq | PE ~30M | plain | 50.2 | 308.8 | 304 MB | 3987 | — | 1.00× |
| --clumpify | 53.5 | 345.3 | 1914 MB | 3380 | −15.2% | 1.07× | ||
| --compression 6 | 264.5 | 1556.6 | 279 MB | 3239 | −18.8% | 5.27× | ||
| --clumpify --compression 6 | 192.5 | 1156.2 | 1858 MB | 2710 | −32.0% | 3.84× | ||
| RNA-seq | PE 93M | plain | 146.4 | 938.1 | 148 MB | 17,034 | — | 1.00× |
| --clumpify | 153.2 | 1046.0 | 2039 MB | 14,455 | −15.1% | 1.05× | ||
| --compression 6 | 864.5 | 5184.0 | 139 MB | 14,658 | −14.0% | 5.90× | ||
| --clumpify --compression 6 | 1956.9 | 3981.8 | 1530 MB | 12,400 | −27.2% | 13.36× | ||
| scRNA-seq 10x Chromium | PE 392M | plain | 383.1 | 2514.1 | 578 MB | 39,575 | — | 1.00× |
| --clumpify | 471.1 | 3112.2 | 2099 MB | 42,033 | +6.2% | 1.23× | ||
| --compression 6 | 2312.7 | 13,550.8 | 146 MB | 32,806 | −17.1% | 6.04× | ||
| --clumpify --compression 6 | TBD | TBD | TBD | TBD | TBD | TBD |
Output (MB): sum of all *.fq.gz in the run's output dir
(R1 + R2 for paired). Saving vs plain: percentage reduction relative
to the plain row of the same dataset. Wall vs plain: ratio of the
configuration's wall time to the plain wall time of the same dataset.
Each plot has 8 dataset groups along the X axis, with 3 bars per group: --clumpify (default L1) · --compression 6 · --clumpify --compression 6. Plain (no flags) is the implicit baseline. The dashed bar with `?` is the still-pending scRNA-seq run.
How to read these together: a configuration is a good
trade if its blue/orange/green bar is tall in the saving plot AND short
in the wall plot. The L1 default (blue) is short in both — minimal cost,
modest saving. --compression 6 alone (orange) trades wall time for saving.
The combined config (green) is the only one that's tall in saving while
often being shorter than orange in wall time — see ATAC-seq, Ribo-seq.
--clumpify --compression 6 often faster than
--compression 6 alone?
Counter-intuitive but real: gzip's deflate is data-dependent in CPU cost,
not just in output size. When clumpify groups reads sharing a 16-mer
minimizer, adjacent records share long substrings; deflate's LZ77 hash
chain finds a long match on the first probe and exits the search early
(the L6 tuning is `nice_match=128, max_chain=128` — sorted data trips
`nice_match` instantly). On unsorted data deflate scans the full chain
trying to find any decent match, settles for a short one, and emits more
literal bytes. Net effect: with sorted input, gzip does less
CPU work per byte AND writes a smaller output
(less I/O). Both bonuses come from the same property — the minimizer
sort effectively pre-does the dictionary search work that deflate would
otherwise do less effectively.
| Dataset | --compression 6 user CPU | --clumpify --compression 6 user CPU | CPU saved |
|---|---|---|---|
| ATAC-seq | 1024 s | 616 s | −40% |
| Ribo-seq | 1557 s | 1156 s | −26% |
| MiSeq amplicon | 145 s | 130 s | −10% |
| WES | 3809 s | 3553 s | −7% |
Same data, plotted as one point per (dataset × config). Up-and-left is best (high saving, low wall cost). Each dataset has 3 dots — one per config — connected with a thin grey line to make it easy to track the same dataset across configs. Hover for tooltips.
What jumps out:
--compression 6 alone (down and right at 21.7%, 4.15×).--clumpify (L1) is mostly free but mostly modest.
Wall ratios are 1.02–1.40× plain across 7 of 8 datasets (only scRNA-seq is
meaningfully slower at 1.23×). Savings range from ~0% (ChIP-seq, long-read,
scRNA-seq) up to 35% (ATAC-seq). The L1 sweet spots are datasets where R1
has strong intrinsic redundancy: ATAC-seq Tn5 footprints, MiSeq amplicons,
RNA-seq highly-expressed transcripts, Ribo-seq ribosome footprints.
--clumpify --compression 6 is the headline configuration.
On every dataset where it has finished, it's the best on both saving (largest
reduction) and — surprisingly — often on wall time vs plain L6: ATAC-seq
L6 alone is 4.15× plain at 22% saving; --clumpify --compression 6
is only 2.37× plain at 49% saving. The reorder pays for itself by giving
gzip cleaner runs to compress, which finishes faster than gzip slogging
through unsorted data at L6.
Cleanest result: every step adds value. --clumpify alone saves
16% with no wall penalty; --compression 6 alone saves 25% at
1.64× wall; combining both saves 32% at 1.51× wall — actually slightly
faster than gzip-L6 alone, because the sorted bins compress more
efficiently. CRISPR-PCR amplicons are nearly identical reads, so this is
the best-case scenario.
L1 reorder gains nothing (peaks aren't dense enough at 28 M reads to fill the small L1 dictionary window). L6 alone saves 14%; clumpify on top of L6 adds only 1 ppt. Largest L1-clumpify wall penalty in the matrix (1.40× plain) for zero benefit — at L1 specifically, ChIP-seq is a bad fit.
Diverse whole-exome coverage gives modest savings across the board: 4% L1-clumpify, 15% L6 alone, 21% combined. Wall penalty is significant at L6 (~6× plain, ~10 minutes wall) — proportional to data volume, not algorithmic. Reorder stacks cleanly with L6 (+5 ppt over L6 alone).
Reorder is essentially a no-op (long reads are unique fragments).
L6 alone saves 9%; clumpify on top adds nothing. Useful negative result:
--clumpify isn't actively harmful on long-read data, but
there's no benefit either.
Strongest reorder beneficiary by a wide margin. L1-clumpify saves 35%; L6 alone saves 22%; combining gets 49%. Counter-intuitively, clumpify+L6 runs faster than L6 alone (98 s vs 172 s) because the bin-sorted gzip members compress so efficiently that less data is written.
Mid-tier beneficiary. L1-clumpify saves 15%; L6 alone saves 19%; combining gets 32%. Same wall-time anomaly as ATAC-seq: clumpify+L6 (193 s) beats L6 alone (264 s).
L1-clumpify saves 15% at almost no wall cost (1.05× plain) — a clear recommendation. L6 alone saves 14% at 5.9× plain wall. Combining gets 27% but the wall-time outlier (13× plain) noted above clouds the picture for this single run.
The interesting case. L1-clumpify is actively harmful (+6%). L6 alone
saves 17% at 6× plain wall (~38 minutes). The --clumpify --compression 6
result is still pending; if it lands above L6-alone's 17% saving, it
validates the hypothesis that R2 fragmentation at L1 is recoverable at L6's
larger dictionary window.
Driver scripts:
/tmp/run_data_types_v2.sh — plain + clumpify (L1) runs/tmp/run_data_types_v2_compress6.sh — compression 6 + clumpify+compression 6 runsLogs and outputs: /Volumes/T7 Shield/clumpy-bench/data_types_v2/*.log
and corresponding /Volumes/T7 Shield/clumpy-bench/data_types_v2/*/
output directories.
All runs sequential, --cores 6 --paired (where applicable),
on Apple M1 Pro / 16 GiB RAM / macOS Darwin 25.4.