Parallel decompression of gzipped text files.
Decompresses text files with a truly parallel algorithm in two passes. (paper for details)
A Linux system on a recent x86_64 CPU is required.
Type:
make
For maximal performance, disable assertions with:
make asserts=0
./gunzip -t 8 file.gz
Counting lines is incredibly faster, because there is no thread synchronization:
./gunzip -l -t 8 file.gz
We provide a small example:
cd example
bash test.sh
Speed is measured in input compressed bytes processed per second.
Threads | gunzip | pugz, full decompression | pugz, only counting lines |
---|---|---|---|
1 | 55 MB/s | 147 MB/s | 145 MB/s |
3 | - | 205 MB/s | 291 MB/s |
6 | - | 228 MB/s | 515 MB/s |
12 | - | 248 MB/s | 769 MB/s |
24 | - | 251 MB/s | 1052 MB/s |
Specs: dual Xeon X5675 (2x 6C/12T), 32 GB RAM NUMA, SSD
On a more recent desktop computer (i7-4770 4C/8T, 16 GB RAM, SSD):
Threads | gunzip | pugz, full decompression | pugz, only counting lines |
---|---|---|---|
1 | 63 MB/s | 172 MB/s | 170 MB/s |
8 | - | 376 MB/s | 565 MB/s |
Tested on a 2.7 GB compressed file, with similar results on a 24 GB file.
Script: https://github.com/Piezoid/pugz/blob/master/example/bigger_benchmark.sh
Note that the synchronization required for writing to the standard output in order ("pugz, full decompression" column) diminishes a lot the speed up. This is not required if your application can process chunks out of order. Also, this issue can be improved in the future with better IO handling.
Contrary to gzip, we don't perform CRC32 calculation. It would roughly inflict a 33% slowdown.
Contrary to the pigz
program which does single-threaded decompression (see https://github.com/madler/pigz/blob/master/pigz.c#L232), pugz found a way to do truly parallel decompression. In a nutshell: the compressed file is splitted into consecutive sections, processed one after the other. Sections are in turn splitted into chunks (one chunk per thread) and will be decompressed in parallel. A first pass decompresses chunks and keeps track of back-references (see e.g. our paper for the definition of that term), but is unable to resolve them. Then, a quick sequential pass is done to resolve the contexts of all chunks. A final parallel pass translates all unresolved back-references and outputs the file.
This is a prototype for proof of concept, so expect some rough corners.
If pugz chokes on some of your large files that you are willing to share, please fill a issue !
Pugz is not yet a production-ready gzip decompressor, and may still crash on some files. Or produce undefined behavior when compiled with make asserts=0
. This is because blocked/multipart files are not currently supported. (support planned)
Only text files with ASCII characters in the range ['\t', '~']
are supported. For example, .tar.gz
files are binary thus won't work. Why binary files are not supported: 1) we optimized the guessing of block positions for ASCII files (resulting in less false positives when scanning the bitstream for a deflate block), and 2) we optimized the code to encode unresolved back-references using 8 bits along with the decompressed text. Both are actually optimizations, so we think that binary decompression is eventually conceivable.
This codebase is currently only a standalone decompression program, but we would like to turn it into a library with some sort of API (e.g. parallel_gzread()
, see issue #6 for discussion) in order to faciliate integration into your favorite software. Right now, the code is a mix between the libdeflate code base (C with gotos) and prototyped C++. It is mostly organized as a header library; however since the source is quite large, we don't think this is the best distribution for it. The middle-ground would be a PIMPL approach with a virtual ABI and some utility wrappers.
Proper error handling is non existent (relies on assertions). Propagating errors between threads can be hard but it must be done eventually.
Could generate/use an index file for faster random access in two+ passes scenario.
This project is licensed under the MIT License.
@inproceedings{pugz,
author = {Kerbiriou, Mael and Chikhi, Rayan},
year = {2019},
month = {05},
pages = {209-217},
title = {Parallel Decompression of Gzip-Compressed Files and Random Access to DNA Sequences},
doi = {10.1109/IPDPSW.2019.00042},
booktitle={2019 IEEE International Parallel and Distributed Processing Symposium Workshops (IPDPSW)}
}
ebiggers for writing libdeflate