ZXC - Asymmetric Lossless Compression Built for Ultra-Fast Decode

June 24, 2026 · View on GitHub

Build & Release Code Quality Code Security Fuzzing

Security Code Coverage OpenSSF Scorecard License

ZXC is a lossless compression C library (with official Rust, Python, Node.js, and Go bindings). It trades compression speed for maximum decode throughput — the appropriate trade-off whenever data is compressed once and read many times: content delivery, embedded systems, FOTA (Firmware Over-The-Air) updates, game assets, and app bundles. It runs on all major architectures (x86_64, ARM64, ARMv7, ARMv6, RISC-V, POWER, s390x, i386) with hand-tuned SIMD paths, and shows particularly strong gains on modern ARM cores (Apple Silicon, AWS Graviton, Google Axion) thanks to a bitstream layout tuned for their deep pipelines.

TL;DR

  • Faster decode than LZ4, at a smaller size. 10–47% faster decode at the default level (best on ARM64), rising to up to 2.3× in the speed-optimized tier, always at an equal-or-better compression ratio. See the benchmarks.
  • Independently verified. Merged into lzbench (@inikep) and TurboBench (@powturbo); every benchmark below is reproducible against 70+ codecs.
  • Cross-platform. x86_64, ARM64, ARMv7, ARMv6, RISC-V, POWER (ppc64el), s390x, i386, with hand-tuned SIMD (SSE2/AVX2/AVX-512 on x86, NEON on ARMv8+).
  • Built for "Write Once, Read Many." Compress once at build time, decompress millions of times at run time.
  • Production-grade. 5B+ fuzzing iterations, ASan/UBSan/Valgrind-clean, SLSA-signed releases, thread-safe API, BSD-3-Clause.
  • Seekable. Built-in seek table for O(1) random-access decompression.
  • Broadly packaged. Conan, vcpkg, Homebrew, and Rust/Python/Node packages.

Quick start

# Install (pick your package manager)
brew install zxc
conan install --requires="zxc/[*]"     # or: vcpkg install zxc

# Compress once, decompress fast
zxc -5 assets.tar assets.tar.zxc
zxc -d assets.tar.zxc assets.tar

Independently verified: ZXC is merged into both major open-source compression benchmark suites — lzbench (master, by @inikep) and TurboBench (master, by @powturbo). Every number in this README is reproducible with either tool, alongside 70+ other codecs.

Design Philosophy: Asymmetric Efficiency

Traditional codecs force a trade-off between symmetric speed (LZ4) and archival density (Zstd). ZXC takes a third path: asymmetric efficiency.

The encoder does the heavy lifting upfront — match selection, optimal parsing, statistics tuning — to emit a bitstream structured for the instruction pipelining and branch prediction of modern CPUs (particularly ARMv8). Complexity is offloaded from the decoder to the encoder, which is exactly the trade-off WORM workloads want.

  • Build time: you compress only once (on CI/CD).
  • Run time: you decompress millions of times (on every user's device). ZXC respects this asymmetry.

👉 Read the Technical Whitepaper

Benchmarks

To ensure consistent performance, benchmarks are automatically executed on every commit via GitHub Actions. We monitor metrics on both x86_64 (Linux) and ARM64 (Apple Silicon M2) runners to track compression speed, decompression speed, and ratios.

(See the latest benchmark logs)

Decompression Speed vs Compressed Size — ARM64 Apple M2

Decompression Speed vs Compressed Size

1. Mobile & Client: Apple Silicon (M2)

Scenario: Game Assets loading, App startup.

TargetZXC vs CompetitorDecompression SpeedRatioVerdict
1. Max SpeedZXC -1 vs LZ4 --fast12,890 MB/s vs 5,620 MB/s 2.29x Faster61.5 vs 62.2 Smaller (-0.7%)ZXC leads in raw throughput.
2. StandardZXC -3 vs LZ4 Default7,051 MB/s vs 4,783 MB/s 1.47x Faster45.8 vs 47.6 Smaller (-1.8%)ZXC outperforms LZ4 in read speed and ratio.
3. Max DensityZXC -6 vs LZ4HC -95,622 MB/s vs 4,508 MB/s 1.25x Faster36.3 vs 36.8 Smaller (-0.5%)ZXC beats LZ4HC on both decode speed and ratio.

2. Cloud Server: Google Axion (ARM Neoverse V2)

Scenario: High-throughput Microservices, ARM Cloud Instances.

TargetZXC vs CompetitorDecompression SpeedRatioVerdict
1. Max SpeedZXC -1 vs LZ4 --fast9,295 MB/s vs 4,912 MB/s 1.89x Faster61.5 vs 62.2 Smaller (-0.7%)ZXC leads in raw throughput.
2. StandardZXC -3 vs LZ4 Default5,321 MB/s vs 4,251 MB/s 1.25x Faster45.8 vs 47.6 Smaller (-1.8%)ZXC outperforms LZ4 in read speed and ratio.
3. Max DensityZXC -6 vs LZ4HC -94,191 MB/s vs 3,827 MB/s 1.10x Faster36.3 vs 36.8 Smaller (-0.5%)ZXC beats LZ4HC on both decode speed and ratio.

3. Build Server: x86_64 (AMD EPYC 9B45 / Zen 5)

Scenario: CI/CD Pipelines compatibility.

TargetZXC vs CompetitorDecompression SpeedRatioVerdict
1. Max SpeedZXC -1 vs LZ4 --fast10,907 MB/s vs 5,302 MB/s 2.06x Faster61.5 vs 62.2 Smaller (-0.7%)ZXC achieves higher throughput.
2. StandardZXC -3 vs LZ4 Default6,040 MB/s vs 5,028 MB/s 1.20x Faster45.8 vs 47.6 Smaller (-1.8%)ZXC offers improved speed and ratio.
3. Max DensityZXC -6 vs LZ4HC -94,764 MB/s vs 4,843 MB/s (decode within 2%)36.3 vs 36.8 Smaller (-0.5%)ZXC wins on ratio; decode trails LZ4HC -9 by ~2%.

4. Production Server: x86_64 (AMD EPYC 7B13 / Zen 3)

Scenario: Mainstream cloud workloads (AWS c6a, Azure HBv3, GCP n2d).

TargetZXC vs CompetitorDecompression SpeedRatioVerdict
1. Max SpeedZXC -1 vs LZ4 --fast7,796 MB/s vs 4,491 MB/s 1.74x Faster61.5 vs 62.2 Smaller (-0.7%)ZXC holds a strong lead on the legacy x86 pipeline.
2. StandardZXC -3 vs LZ4 Default4,308 MB/s vs 3,891 MB/s 1.11x Faster45.8 vs 47.6 Smaller (-1.8%)ZXC delivers faster decode and smaller output.
3. Max DensityZXC -6 vs LZ4HC -93,508 MB/s vs 3,732 MB/s (decode within 6%)36.3 vs 36.8 Smaller (-0.5%)ZXC wins on ratio; decode trails LZ4HC -9 by ~6% on Zen 3.

Decompression Speed: ZXC vs LZ4 family at equivalent ratio tiers, across 4 CPUs (Fast ≈ 62%, Default ≈ 47%, High ≈ 37%)

Decompression Speed: ZXC vs LZ4 family at equivalent ratio tiers

Effective Throughput : Ratio-Normalized Decode across ARM64 and x86 (decode x 100 / ratio%, LZ4 baseline = 1.00x)

Effective Throughput

What is Effective Throughput?

Raw decode speed misses half the picture: in real workloads (asset streaming, container pulls, microservice payloads), the decoder is fed by a compressed-byte source - disk, network, inter-core - whose bandwidth is the bottleneck. The right question is how much original data is delivered per MB of compressed input.

Formula: Effective (MB/s) = Decode × 100 / Ratio (%): combines decode speed and ratio in one number. Every ZXC level sits above LZ4 on every architecture, peaking at 2.0x on Apple Silicon and ranging 1.15x–1.72x on x86 and ARM cloud platforms.

Benchmark ARM64 (Apple Silicon M2)

Benchmarks were conducted using lzbench 2.2.1 (from @inikep), compiled with Clang 21.0.0 using MOREFLAGS="-march=native" on macOS Tahoe 26.4 (Build 25E246). The reference hardware is an Apple M2 processor (ARM64). All performance metrics reflect single-threaded execution on the standard Silesia Corpus and the benchmark made use of silesia.tar, which contains tarred files from the Silesia compression corpus.

Compressor nameCompressionDecompress.Compr. sizeRatioFilename
memcpy52913 MB/s52862 MB/s211947520100.001 files
zxc 0.12.0 -1878 MB/s12890 MB/s13035614761.501 files
zxc 0.12.0 -2588 MB/s10676 MB/s11363386653.611 files
zxc 0.12.0 -3257 MB/s7051 MB/s9705144445.791 files
zxc 0.12.0 -4176 MB/s6686 MB/s9039285742.651 files
zxc 0.12.0 -5104 MB/s6289 MB/s8534125640.271 files
zxc 0.12.0 -612.7 MB/s5622 MB/s7688201036.271 files
lz4 1.10.0815 MB/s4783 MB/s10088080047.601 files
lz4 1.10.0 --fast -171354 MB/s5620 MB/s13173280262.151 files
lz4hc 1.10.0 -948.4 MB/s4508 MB/s7788444836.751 files
lzav 5.7 -1658 MB/s3869 MB/s8464473239.941 files
snappy 1.2.2882 MB/s3264 MB/s10141544347.851 files
zstd 1.5.7 --fast --1726 MB/s2541 MB/s8691629441.011 files
zstd 1.5.7 -1647 MB/s1808 MB/s7319370434.531 files
zlib 1.3.1 -1150 MB/s412 MB/s7725902936.451 files

Benchmark ARM64 (Google Axion Neoverse-V2)

Benchmarks were conducted using lzbench 2.2.1 (from @inikep), compiled with GCC 14.3.0 using MOREFLAGS="-march=native" on 64-bit Linux. The reference hardware is a Google Axion (Neoverse-V2) processor on a Google Cloud C4A instance (ARM64, 1 thread per core). All performance metrics reflect single-threaded execution on the standard Silesia Corpus and the benchmark made use of silesia.tar, which contains tarred files from the Silesia compression corpus.

Compressor nameCompressionDecompress.Compr. sizeRatioFilename
memcpy24656 MB/s24056 MB/s211947520100.001 files
zxc 0.12.0 -1872 MB/s9295 MB/s13035614761.501 files
zxc 0.12.0 -2589 MB/s7719 MB/s11363386653.611 files
zxc 0.12.0 -3246 MB/s5321 MB/s9705144445.791 files
zxc 0.12.0 -4170 MB/s5066 MB/s9039285742.651 files
zxc 0.12.0 -599.7 MB/s4728 MB/s8534125640.271 files
zxc 0.12.0 -611.8 MB/s4191 MB/s7688201036.271 files
lz4 1.10.0728 MB/s4251 MB/s10088080047.601 files
lz4 1.10.0 --fast -171273 MB/s4912 MB/s13173280262.151 files
lz4hc 1.10.0 -921.3 MB/s3827 MB/s7788444836.751 files
lzav 5.7 -1540 MB/s2718 MB/s8464473239.941 files
snappy 1.2.2753 MB/s2312 MB/s10141544347.851 files
zstd 1.5.7 --fast --1604 MB/s2285 MB/s8691629441.011 files
zstd 1.5.7 -1522 MB/s1639 MB/s7319370434.531 files
zlib 1.3.1 -1115 MB/s389 MB/s7725902936.451 files

Benchmark x86_64 (AMD EPYC 9B45)

Benchmarks were conducted using lzbench 2.2.1 (from @inikep), compiled with GCC 14.3.0 using MOREFLAGS="-march=native" on 64-bit Linux. The reference hardware is an AMD EPYC 9B45 processor on a Google Cloud C4D instance (x86_64, SMT disabled — 1 thread per core). All performance metrics reflect single-threaded execution on the standard Silesia Corpus and the benchmark made use of silesia.tar, which contains tarred files from the Silesia compression corpus.

Compressor nameCompressionDecompress.Compr. sizeRatioFilename
memcpy25130 MB/s25640 MB/s211947520100.001 files
zxc 0.12.0 -1868 MB/s10907 MB/s13035614761.501 files
zxc 0.12.0 -2589 MB/s9725 MB/s11363386653.611 files
zxc 0.12.0 -3243 MB/s6040 MB/s9705144445.791 files
zxc 0.12.0 -4167 MB/s5724 MB/s9039285742.651 files
zxc 0.12.0 -599.8 MB/s5405 MB/s8534125640.271 files
zxc 0.12.0 -612.7 MB/s4764 MB/s7688201036.271 files
lz4 1.10.0771 MB/s5028 MB/s10088080047.601 files
lz4 1.10.0 --fast -171290 MB/s5302 MB/s13173280262.151 files
lz4hc 1.10.0 -945.3 MB/s4843 MB/s7788444836.751 files
lzav 5.7 -1606 MB/s3574 MB/s8464473239.941 files
snappy 1.2.2772 MB/s2085 MB/s10151207647.891 files
zstd 1.5.7 --fast --1328 MB/s2425 MB/s8691629441.011 files
zstd 1.5.7 -1600 MB/s1879 MB/s7319370434.531 files
zlib 1.3.1 -1136 MB/s392 MB/s7725902936.451 files

Benchmark x86_64 (AMD EPYC 7B13)

Benchmarks were conducted using lzbench 2.2.1 (from @inikep), compiled with GCC 14.3.0 using MOREFLAGS="-march=native" on 64-bit Linux. The reference hardware is an AMD EPYC 7B13 64-Core processor on a Google Cloud C2D instance (x86_64, SMT disabled — 1 thread per core). All performance metrics reflect single-threaded execution on the standard Silesia Corpus and the benchmark made use of silesia.tar, which contains tarred files from the Silesia compression corpus.

Compressor nameCompressionDecompress.Compr. sizeRatioFilename
memcpy24142 MB/s24155 MB/s211947520100.001 files
zxc 0.12.0 -1724 MB/s7796 MB/s13035614761.501 files
zxc 0.12.0 -2486 MB/s6477 MB/s11363386653.611 files
zxc 0.12.0 -3205 MB/s4308 MB/s9705144445.791 files
zxc 0.12.0 -4143 MB/s4133 MB/s9039285742.651 files
zxc 0.12.0 -585.8 MB/s3992 MB/s8534125640.271 files
zxc 0.12.0 -610.6 MB/s3508 MB/s7688201036.271 files
lz4 1.10.0640 MB/s3891 MB/s10088080047.601 files
lz4 1.10.0 --fast -171111 MB/s4491 MB/s13173280262.151 files
lz4hc 1.10.0 -937.1 MB/s3732 MB/s7788444836.751 files
lzav 5.7 -1443 MB/s2886 MB/s8464473239.941 files
snappy 1.2.2665 MB/s1739 MB/s10151207647.891 files
zstd 1.5.7 --fast --1488 MB/s1789 MB/s8691629441.011 files
zstd 1.5.7 -1443 MB/s1342 MB/s7319370434.531 files
zlib 1.3.1 -1106 MB/s359 MB/s7725902936.451 files

Installation

ZXC is packaged across major ecosystems and kept current by their maintainers:

ConanCenter Vcpkg Homebrew Debian 14 Ubuntu 26.10

Crates.io PyPi npm

Option 1: Download Release (GitHub)

  1. Go to the Releases page.

  2. Download the archive matching your architecture (replace <version> with the release, e.g. 0.12.0):

    macOS:

    • zxc-<version>-macos-arm64.tar.gz (NEON optimizations included).

    Linux:

    • zxc-<version>-linux-arm64.tar.gz (NEON optimizations included).
    • zxc-<version>-linux-x86_64.tar.gz (Runtime dispatch for AVX2/AVX512).

    Windows:

    • zxc-<version>-windows-x86_64.zip (Runtime dispatch for AVX2/AVX512).
    • zxc-<version>-windows-arm64.zip (NEON optimizations included).
  3. Verify, then extract. Every archive is signed via SLSA build provenance; the SHA-256 of each asset is also shown directly on the GitHub release page:

    # Authenticity + integrity in one shot (SLSA — recommended)
    gh attestation verify zxc-<version>-linux-x86_64.tar.gz --repo hellobertrand/zxc
    
    # Extract
    tar -xzf zxc-<version>-linux-x86_64.tar.gz
    sudo cp -r zxc-<version>-linux-x86_64/* /usr/local/
    

    Each archive contains a versioned top-level directory with:

    bin/zxc                          # CLI binary
    include/                         # C headers (zxc.h, zxc_buffer.h, ...)
    lib/libzxc.a                     # Static library
    lib/pkgconfig/libzxc.pc          # pkg-config support
    lib/cmake/zxc/zxcConfig.cmake    # CMake find_package(zxc) support
    
  4. Use in your project:

    CMake:

    find_package(zxc REQUIRED)
    target_link_libraries(myapp PRIVATE zxc::zxc_lib)
    

    pkg-config:

    cc myapp.c $(pkg-config --cflags --libs libzxc) -o myapp
    

Option 2: vcpkg

Classic mode:

vcpkg install zxc

Manifest mode (add to vcpkg.json):

{
  "dependencies": ["zxc"]
}

Then in your CMake project:

find_package(zxc CONFIG REQUIRED)
target_link_libraries(myapp PRIVATE zxc::zxc_lib)

Option 3: Conan

You also can download and install zxc using the Conan package manager:

    conan install -r conancenter --requires="zxc/[*]" --build=missing

Or add to your conanfile.txt:

[requires]
zxc/[*]

The zxc package in Conan Center is kept up to date by ConanCenterIndex contributors. If the version is out of date, please create an issue or pull request on the Conan Center Index repository.

Option 4: Homebrew

brew install zxc

The formula is maintained in homebrew-core.

Option 5: Meson Subproject

zxc ships a native meson.build, so any Meson project can pull it in as a subproject or via WrapDB.

1. Create subprojects/zxc.wrap:

[wrap-git]
url = https://github.com/hellobertrand/zxc.git
revision = head
depth = 1

[provide]
libzxc = libzxc_dep

2. Use the dependency in your meson.build:

zxc_dep = dependency('libzxc', fallback : ['zxc', 'libzxc_dep'])
executable('myapp', 'main.c', dependencies : zxc_dep)

3. Build:

meson setup build
meson compile -C build

When consumed as a subproject, only the library is built (CLI and tests are skipped automatically).

Option 6: Building from Source (CMake)

Requirements: CMake (3.14+), C17 Compiler (Clang/GCC/MSVC).

git clone https://github.com/hellobertrand/zxc.git
cd zxc
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel

# Run tests
ctest --test-dir build -C Release --output-on-failure

# CLI usage
./build/zxc --help

# Install library, headers, and CMake/pkg-config files
sudo cmake --install build

CMake Options

OptionDefaultDescription
BUILD_SHARED_LIBSOFFBuild shared libraries instead of static (libzxc.so, libzxc.dylib, zxc.dll)
ZXC_NATIVE_ARCHONEnable -march=native for maximum performance
ZXC_ENABLE_LTOONEnable Link-Time Optimization (LTO)
ZXC_PGO_MODEOFFProfile-Guided Optimization mode (OFF, GENERATE, USE)
ZXC_BUILD_CLIONBuild command-line interface
ZXC_BUILD_TESTSONBuild unit tests
ZXC_ENABLE_COVERAGEOFFEnable code coverage generation (disables LTO/PGO)
ZXC_DISABLE_SIMDOFFDisable hand-written SIMD paths (AVX2/AVX512/NEON)
# Build shared library
cmake -B build -DBUILD_SHARED_LIBS=ON

# Portable build (without -march=native)
cmake -B build -DZXC_NATIVE_ARCH=OFF

# Library only (no CLI, no tests)
cmake -B build -DZXC_BUILD_CLI=OFF -DZXC_BUILD_TESTS=OFF

# Code coverage build
cmake -B build -DZXC_ENABLE_COVERAGE=ON

# Disable explicit SIMD code paths (compiler auto-vectorisation is unaffected)
cmake -B build -DZXC_DISABLE_SIMD=ON

Profile-Guided Optimization (PGO)

PGO uses runtime profiling data to optimize branch layout, inlining decisions, and code placement.

Step 1 - Build with instrumentation:

cmake -B build -DCMAKE_BUILD_TYPE=Release -DZXC_PGO_MODE=GENERATE
cmake --build build --parallel

Step 2 - Run a representative workload to collect profile data:

# Run the test suite (exercises all block types and compression levels)
./build/zxc_test

# Or compress/decompress representative data
./build/zxc -b your_data_file

Step 3 - (Clang only) Merge raw profiles:

# Clang generates .profraw files that must be merged before use
llvm-profdata merge -output=build/pgo/default.profdata build/pgo/*.profraw

GCC uses a directory-based format and does not require this step.

Step 4 - Rebuild with profile data:

cmake -B build -DCMAKE_BUILD_TYPE=Release -DZXC_PGO_MODE=USE
cmake --build build --parallel

Packaging Status

Packaging status


Compression Levels

  • Level 1, 2 (Fast): Optimized for real-time assets (Gaming, UI).
  • Level 3, 4 (Balanced): A strong middle-ground offering efficient compression speed and a ratio superior to LZ4.
  • Level 5 (Compact): A good choice for Embedded and Firmware. Better compression than LZ4 and significantly faster decoding than Zstd.
  • Level 6 (Max): Highest ratio tier, matching LZ4-HC while keeping ZXC's decode advantage. Best for Archival and write-once / read-many workloads where compression time is amortized over many reads.

Block Size Tuning

The default block size is 512 KB, tuned for bulk/archival workloads where ratio and decompression throughput matter most. For memory-constrained or streaming use cases, 256 KB blocks halve the per-context memory footprint at a small cost in ratio and decompression speed.

Why larger blocks help: Each block starts with a cold hash table, so the LZ match-finder has no history and produces more literals until the table warms up. Doubling the block size halves the number of cold-start penalties, improving both ratio and decompression speed.

Block Sizecctx memorydctx memoryRatio (level -3)Decompression gain vs 256 KB
256 KB~1.03 MB~256 KB46.36%
512 KB (default)~1.78 MB~512 KB45.81% (−0.55 pp)+1% to +8% depending on CPU
# CLI — fall back to 256 KB blocks (e.g. embedded / streaming)
zxc -B 256K -5 input_file output_file

# API
zxc_compress_opts_t opts = {
    .level      = ZXC_LEVEL_COMPACT,
    .block_size = 256 * 1024,
};

Guideline: Stick with 512 KB (default) for bulk compression pipelines, CI/CD asset packaging, and high-throughput servers. Use 256 KB (-B 256K) for streaming, embedded, or memory-constrained environments.


Dictionary Compression

For workloads compressed in small blocks (4 KB–128 KB), a pre-trained dictionary dramatically improves compression ratio. Because the dictionary prefills the LZ77 sliding window at the start of each block, the benefit is per-block: a block only has its own preceding bytes as history, so the smaller the block, the more it leans on the dictionary for representative patterns. This applies whether the input is a single small payload or a large payload split into many small blocks — any time the block size is small enough that early bytes would otherwise lack history to match against.

Typical use cases: JSON API responses, small game assets, structured logs, key-value store records, RPC messages, and any large but homogeneous corpus compressed in small blocks for random access (e.g. seekable archives).

Training a dictionary

# Train a dictionary from a corpus of similar files.
# Without -o the dictionary is written as ./dictionary_<dict_id>.zxd.
zxc --train samples/*.json

# Choose the output file explicitly with -o:
zxc --train -o corpus.zxd samples/*.json

# Or point -o at a directory: the dictionary is saved as dictionary_<dict_id>.zxd
# inside it (the dict_id embeds in the name), e.g. dicts/dictionary_bc46eec1.zxd
zxc --train -o dicts/ samples/*.json
// C API
const void* samples[] = { buf1, buf2, buf3 };
size_t sizes[] = { len1, len2, len3 };
uint8_t dict[32768];
int64_t dict_sz = zxc_train_dict(samples, sizes, 3, dict, sizeof(dict));

Compressing with a dictionary

# CLI — the same dictionary is required to decompress (pass it with -D)
zxc -z -D corpus.zxd input.json
zxc -d -D corpus.zxd input.json.zxc
// C API — compression
zxc_compress_opts_t copts = {
    .level = ZXC_LEVEL_DEFAULT,
    .dict = dict_content,
    .dict_size = dict_sz,
};
int64_t compressed_size = zxc_compress(src, src_size, dst, dst_cap, &copts);

// C API — decompression (same dictionary required)
zxc_decompress_opts_t dopts = {
    .dict = dict_content,
    .dict_size = dict_sz,
};
int64_t original_size = zxc_decompress(compressed, comp_size, out, out_cap, &dopts);

The dictionary is stored as an external .zxd file and referenced by a 32-bit ID (dict_id) in the ZXC file header. The same dictionary is required to decompress and must be supplied explicitly with -D — there is no auto-lookup. Decompressing an archive that needs a dictionary without supplying one returns ZXC_ERROR_DICT_REQUIRED; supplying the wrong one returns ZXC_ERROR_DICT_MISMATCH. Training to a directory names the file dictionary_<dict_id>.zxd. See FORMAT.md §12 for the full specification.


Usage

1. CLI

The CLI is perfect for benchmarking or manually compressing assets.

# Basic Compression (Level 3 is default)
zxc -z input_file output_file

# High Compression (Level 5)
zxc -z -5 input_file output_file

# Seekable Archive (enables O(1) random-access decompression)
zxc -z -S input_file output_file

# -z for compression can be omitted
zxc input_file output_file

# as well as output file; it will be automatically assigned to input_file.zxc
zxc input_file

# Decompression
zxc -d compressed_file output_file

# When installed, "unzxc" is an alias for "zxc -d"
unzxc compressed_file output_file

# Benchmark Mode (Testing speed on your machine)
zxc -b input_file

Using with tar

ZXC works as a drop-in external compressor for tar (reads stdin, writes stdout, returns 0 on success):

# GNU tar (Linux)
tar -I 'zxc -5' -cf archive.tar.zxc data/
tar -I 'zxc -d' -xf archive.tar.zxc

# bsdtar (macOS)
tar --use-compress-program='zxc -5' -cf archive.tar.zxc data/
tar --use-compress-program='zxc -d' -xf archive.tar.zxc

# Pipes (universal)
tar cf - data/ | zxc > archive.tar.zxc
zxc -d < archive.tar.zxc | tar xf -

2. API

ZXC provides a thread-safe API with two usage patterns. Parameters are passed through dedicated options structs, making call sites self-documenting and forward-compatible.

Buffer API (In-Memory)

#include "zxc.h"

// Compression
uint64_t bound = zxc_compress_bound(src_size);
zxc_compress_opts_t c_opts = {
    .level            = ZXC_LEVEL_DEFAULT,
    .checksum_enabled = 1,
    /* .block_size = 0 -> 512 KB default */
};
int64_t compressed_size = zxc_compress(src, src_size, dst, bound, &c_opts);

// Decompression
zxc_decompress_opts_t d_opts = { .checksum_enabled = 1 };
int64_t decompressed_size = zxc_decompress(src, src_size, dst, dst_capacity, &d_opts);

Stream API (Files, Multi-Threaded)

#include "zxc.h"

// Compression (auto-detect threads, level 3, checksum on)
zxc_compress_opts_t c_opts = {
    .n_threads        = 0,               // 0 = auto
    .level            = ZXC_LEVEL_DEFAULT,
    .checksum_enabled = 1,
    /* .block_size = 0 -> 512 KB default */
};
int64_t bytes_written = zxc_stream_compress(f_in, f_out, &c_opts);

// Decompression
zxc_decompress_opts_t d_opts = { .n_threads = 0, .checksum_enabled = 1 };
int64_t bytes_out = zxc_stream_decompress(f_in, f_out, &d_opts);

Reusable Context API (Low-Latency / Embedded)

For tight loops (e.g. filesystem plug-ins) where per-call malloc/free overhead matters, use opaque reusable contexts. Options are sticky - settings from zxc_create_cctx() are reused when passing NULL:

#include "zxc.h"

zxc_compress_opts_t opts = { .level = 3, .checksum_enabled = 0 };
zxc_cctx* cctx = zxc_create_cctx(&opts);   // allocate once, settings remembered
zxc_dctx* dctx = zxc_create_dctx();        // allocate once

// reuse across many blocks - NULL reuses sticky settings:
int64_t csz = zxc_compress_cctx(cctx, src, src_sz, dst, dst_cap, NULL);
int64_t dsz = zxc_decompress_dctx(dctx, dst, csz, out, src_sz, NULL);

zxc_free_cctx(cctx);
zxc_free_dctx(dctx);

Features:

  • Caller-allocated buffers with explicit bounds
  • Thread-safe (stateless)
  • Configurable block sizes (4 KB – 2 MB, powers of 2)
  • Multi-threaded streaming (auto-detects CPU cores)
  • Optional checksum validation
  • Reusable contexts for high-frequency call sites
  • Seekable archives: optional seek table for O(1) random-access decompression (.seekable = 1)

👉 See complete examples and advanced usage

Language Bindings

Crates.io PyPi npm

Official wrappers maintained in this repository:

LanguagePackage ManagerInstall CommandDocumentationAuthor
Rustcrates.iocargo add zxc-compressREADME@hellobertrand
PythonPyPIpip install zxc-compressREADME@nuberchardzer1
Node.jsnpmnpm install zxc-compressREADME@hellobertrand
Gogo getgo get github.com/hellobertrand/zxc/wrappers/goREADME@hellobertrand
WASMBuild from sourceemcmake cmake -B build-wasm && cmake --build build-wasmREADME@hellobertrand

Community-maintained bindings:

LanguagePackage ManagerInstall CommandRepositoryAuthor
Gopkg.go.devgo get github.com/meysam81/go-zxchttps://github.com/meysam81/go-zxc@meysam81
Nimnimblenimble install zxchttps://github.com/openpeeps/zxc-nim@georgelemon
Free PascalBuild from sourceClone the repositoryhttps://github.com/Xelitan/Free-Pascal-port-of-ZXC-compressor-decompressor@Xelitan

Format & Conformance

The ZXC on-disk wire format is fully specified in docs/FORMAT.md (format version 6), so any third party can build an independent, interoperable decoder.

Upgrading from a v5 build? Format v6 is a deliberate break with v5 and v6 tools reject v5 archives. See docs/MIGRATION.md to convert existing archives.

Two complementary, byte-frozen suites guard that format:

  • Decoder conformanceconformance/ ships public reference vectors: valid/*.zxc streams paired with their expected decompressed output, plus invalid/*.zxc streams that a correct decoder must reject. Point your own decoder at them to prove interoperability — no dependency on this implementation. Run locally via the conformance CTest.
  • Wire-format stabilitytests/format/ pins the exact bytes the encoder emits for every block type and integrity field. A dedicated CI job (golden.yml) fails on any single-byte drift, so a format change can only ever be deliberate.

The distinction: conformance freezes decoder behaviour (decode(x) == expected), while the golden suite freezes the encoder's bytes. Together they make the format both interoperable and stable.

Safety & Quality

  • Unit Tests: Comprehensive test suite with CTest integration.
  • Continuous Fuzzing: Integrated with ClusterFuzzLite suites — 5+ billion iterations accumulated to date across compress, decompress, streaming and seekable API surfaces.
  • Static Analysis: Checked with Cppcheck & Clang Static Analyzer.
  • CodeQL Analysis: GitHub Advanced Security scanning for vulnerabilities.
  • Snyk: Continuous security and code analysis for dependencies and source.
  • Code Coverage: Automated tracking with Codecov integration.
  • Dynamic Analysis: Validated with Valgrind and ASan/UBSan in CI pipelines.
  • Safe API: Explicit buffer capacity is required for all operations.

License & Credits

ZXC Copyright © 2025-2026, Bertrand Lebonnois and contributors. Licensed under the BSD 3-Clause License. See LICENSE for details.

Third-Party Components:

  • rapidhash by Nicolas De Carli (MIT) - Used for high-speed, platform-independent checksums.