Raising this before any PR, per the dependency rule in CONTRIBUTING.md. It is a pure-Rust crate, so it does not carry the objections that closed #162 and #177, but it is still a dependency and the decision is yours.
What it is
|
|
| Crate |
rapidgzip-rust, @rob-p COMBINE-lab (the salmon / alevin-fry group) |
| Licence |
BSD-3-Clause / MIT / Apache-2.0 triple |
| Non-Rust dependencies |
none — no cc, no cmake, no system library |
| What it does |
Parallel gzip decompression, treating a gzip file as independently verifiable members; handles concatenated gzip and BGZF |
| Interfaces |
a push API to std::io::Write, and a std::io::Read + Send adapter that drops into an existing parser |
Why it might matter here
Sequencing FASTQ is gzipped. Effectively always. Every ENA and SRA download, every sequencing facility delivery, every 10x fastqs/ directory. This repository assumes it too: CONTRIBUTING.md tells a contributor to fetch ERR12389696_1.fastq.gz from ENA and keeps it compressed, and test/data_setup.sh, test/run_tests.sh and the rest of the harness read .fastq.gz throughout. Uncompressed FASTQ is the exception, not the rule.
So this is not about one mode. Decompression sits on the critical path of every rustar run that reads real data — bulk RNA-seq, two-pass, solo, chimeric, all of it.
Today src/io/fastq.rs detects .gz and hands it to flate2 with the zlib-rs backend. That is pure Rust and already faster than miniz_oxide, but it is single-threaded per file: one producer thread inflates while up to --runThreadN workers wait on it. The more cores a run is given, the larger the share of the machine that can be idle behind one decompressor.
I have not measured that share, and I do not want to open a PR on the assumption that it is large. What I can give is the shape: a human PBMC run today read 1.6 GB of gzip for 20 M read pairs and finished the whole alignment in about 2.5 minutes at 14 threads. If inflating that input is a meaningful part of the 2.5 minutes, this crate is the fix. If it is not, the dependency buys nothing and this should be closed.
What I would do before proposing anything
- Profile a gzipped-input run and get the actual share of wall-clock spent inflating, at 1 / 8 / 16 threads. The interesting number is how that share grows with thread count, since that is where a serial producer hurts.
- If it is large, A/B the two decompressors on identical input, with interleaved medians, and confirm byte-identical output.
- Only then a PR, carrying those numbers.
The honest counterweights
flate2 is already a dependency and already pure Rust. This would be a second decompressor, not a replacement for a C one, so the tree grows rather than trades.
- The crate is young. Its own README describes "a substantial generic-stream scaling gap against ISA-L-enabled C++ rapidgzip", so it is not yet at the ceiling of the approach.
- Its BGZF support overlaps
noodles-bgzf, already here for BAM. Two paths to one format is a maintenance question by itself.
- Parallel decompression must not make output depend on thread count. Determinism is a correctness property here, so record ordering would need the same guarantee the aligner already has.
Happy to run step 1 and report the number either way — that is a measurement, not a PR, and it settles whether this is worth your time.
Raising this before any PR, per the dependency rule in
CONTRIBUTING.md. It is a pure-Rust crate, so it does not carry the objections that closed #162 and #177, but it is still a dependency and the decision is yours.What it is
rapidgzip-rust, @rob-p COMBINE-lab (the salmon / alevin-fry group)cc, nocmake, no system librarystd::io::Write, and astd::io::Read + Sendadapter that drops into an existing parserWhy it might matter here
Sequencing FASTQ is gzipped. Effectively always. Every ENA and SRA download, every sequencing facility delivery, every 10x
fastqs/directory. This repository assumes it too:CONTRIBUTING.mdtells a contributor to fetchERR12389696_1.fastq.gzfrom ENA and keeps it compressed, andtest/data_setup.sh,test/run_tests.shand the rest of the harness read.fastq.gzthroughout. Uncompressed FASTQ is the exception, not the rule.So this is not about one mode. Decompression sits on the critical path of every rustar run that reads real data — bulk RNA-seq, two-pass, solo, chimeric, all of it.
Today
src/io/fastq.rsdetects.gzand hands it toflate2with thezlib-rsbackend. That is pure Rust and already faster thanminiz_oxide, but it is single-threaded per file: one producer thread inflates while up to--runThreadNworkers wait on it. The more cores a run is given, the larger the share of the machine that can be idle behind one decompressor.I have not measured that share, and I do not want to open a PR on the assumption that it is large. What I can give is the shape: a human PBMC run today read 1.6 GB of gzip for 20 M read pairs and finished the whole alignment in about 2.5 minutes at 14 threads. If inflating that input is a meaningful part of the 2.5 minutes, this crate is the fix. If it is not, the dependency buys nothing and this should be closed.
What I would do before proposing anything
The honest counterweights
flate2is already a dependency and already pure Rust. This would be a second decompressor, not a replacement for a C one, so the tree grows rather than trades.noodles-bgzf, already here for BAM. Two paths to one format is a maintenance question by itself.Happy to run step 1 and report the number either way — that is a measurement, not a PR, and it settles whether this is worth your time.