# Kanzi Compression Levels 0-9: Complete Guide to Trade-offs and Performance

> Explore Kanzi compression levels 0-9 and understand the trade-offs between speed, memory, and compression ratios. Make informed choices for optimal performance.

- Repository: [flanglet/kanzi-cpp](https://github.com/flanglet/kanzi-cpp)
- Tags: deep-dive
- Published: 2026-03-02

---

**Kanzi compression levels 0 through 9 map to preset combinations of transforms and entropy codecs defined in `BlockCompressor::getTransformAndCodec`, where higher levels trade speed and memory for superior compression ratios by employing algorithms ranging from simple LZX to complex BWT and TPAQX pipelines.**

The `flanglet/kanzi-cpp` repository implements a tiered compression system where the `-l` or `--level` argument selects predefined pipelines. Understanding these Kanzi compression levels is essential for optimizing the balance between throughput, memory consumption, and archive size.

## How Kanzi Compression Levels Work

The level system is hard-coded in [`src/app/BlockCompressor.cpp`](https://github.com/flanglet/kanzi-cpp/blob/main/src/app/BlockCompressor.cpp) within the `getTransformAndCodec` function (lines 21-73). When you specify `-l N`, the command-line parser in [`src/app/Kanzi.cpp`](https://github.com/flanglet/kanzi-cpp/blob/main/src/app/Kanzi.cpp) (lines 94-108) stores the value in the context object. The `BlockCompressor` constructor then retrieves this value and invokes `getTransformAndCodec` to determine the specific transform string and entropy codec.

The function returns two strings that are stored in the context as `"transform"` and `"entropy"`. These strings drive the `TransformFactory` and entropy codec factories when `CompressedOutputStream` instantiates the compression pipeline.

## Detailed Breakdown of Kanzi Compression Levels 0-9

Each level corresponds to a specific transform pipeline and entropy codec combination:

| Level | Transform Pipeline | Entropy Codec | Typical Use Case | Relative Speed |
|-------|-------------------|---------------|------------------|----------------|
| **0** | `NONE` | `NONE` | Pass-through testing | Fastest (no work) |
| **1** | `LZX` | `NONE` | Quick-look compression, low-latency pipelines | ~1% of level 9 |
| **2** | `DNA+LZ` | `HUFFMAN` | Small binary blobs, DNA-style data | ~3% of level 9 |
| **3** | `TEXT+UTF+PACK+MM+LZX` | `HUFFMAN` | Default for generic files | ~10% of level 9 |
| **4** | `TEXT+UTF+EXE+PACK+MM+ROLZ` | `NONE` | Avoiding block-checksum overhead | ~20% of level 9 |
| **5** | `TEXT+UTF+BWT+RANK+ZRLT` | `ANS0` | Highly repetitive text | ~35% of level 9 |
| **6** | `TEXT+UTF+BWT+SRT+ZRLT` | `FPAQ` | Large textual corpora | ~55% of level 9 |
| **7** | `LZP+TEXT+UTF+BWT+LZP` | `CM` | Mixed binary-text workloads | ~70% of level 9 |
| **8** | `EXE+RLT+TEXT+UTF+DNA` | `TPAQ` | Binaries and DNA-like data | ~90% of level 9 |
| **9** | `EXE+RLT+TEXT+UTF+DNA` | `TPAQX` | Maximum compression | Reference (slowest) |

The speed percentages derive from empirical benchmarks in the repository README. For example, compressing *silesia.tar* takes approximately 11,618 ms at level 9 versus 72 ms at level 1.

## Performance and Resource Trade-offs

### Transform Complexity

Lower levels employ simple dictionary-based transforms like `LZX` and `DNA+LZ`. Mid-range levels introduce `TEXT` and `UTF` preprocessing filters. High levels activate the **Burrows-Wheeler Transform (BWT)** in levels 5-7, while levels 8-9 add `EXE` (executable filters) and `RLT` (run-length transforms).

### Entropy Coding Overhead

The entropy codec selection significantly impacts CPU and memory:
- **`NONE`**: Zero overhead, direct byte storage
- **`HUFFMAN`**: Fast, low-memory Huffman coding
- **`ANS0`/`FPAQ`**: Asymmetric numeral systems and neural predictive coding
- **`TPAQ`/`TPAQX`**: Complex context mixing models requiring substantial memory and computation

### Memory Considerations

The default block size is 4 MiB (`DEFAULT_BLOCK_SIZE` in [`BlockCompressor.cpp`](https://github.com/flanglet/kanzi-cpp/blob/main/BlockCompressor.cpp) lines 38-40). While levels do not automatically alter block size, high levels benefit from larger blocks. You can enable automatic block sizing with `--block=AUTO` or specify manually (e.g., `--block=64M`).

## Recommendations by Use Case

| Scenario | Recommended Level | Rationale |
|----------|-----------------|-----------|
| **Real-time streaming or low-latency services** | **0 or 1** | No transform or only fast LZX; negligible CPU overhead |
| **General-purpose archiving (speed priority)** | **3 (default)** | Balanced `TEXT+UTF+PACK+MM+LZX` with Huffman; ~10% of level 9 time |
| **Large text logs, CSV, or source code** | **5 or 6** | BWT-based pipelines with ANS0/FPAQ for repetitive text |
| **Mixed binary/text bundles** | **7** | LZP-enhanced pipeline handles both patterns efficiently |
| **Maximum compression (offline backups)** | **9** | Full `EXE+RLT+TEXT+UTF+DNA` with `TPAQX`; smallest files, 10-20× slower |
| **Limited RAM (embedded devices)** | **0-3** | Memory usage stays under 50 MiB; higher levels allocate BWT/TPAQX buffers |
| **Custom transform experimentation** | **Manual** | Skip `-l`; use `--transform` and `--entropy` directly |

> **Tip:** When using level 9, ensure block size is at least 4 MiB or larger (`--block=64M`). The auto-block heuristic (`--block=AUTO`) selects size proportional to input divided by job count, improving throughput for large files.

## Implementation Examples

### Command-Line Usage

```bash

# Fast compression for low-latency pipelines (level 1)

kanzi -c -i input.bin -o output.knz -l 1

# Default balanced compression (level 3)

kanzi -c -i input.txt -o output.knz

# Maximum compression with multi-threading (level 9)

kanzi -c -i large.tar -o large.knz -l 9 -j 4

```

*Flag handling is implemented in [`src/app/Kanzi.cpp`](https://github.com/flanglet/kanzi-cpp/blob/main/src/app/Kanzi.cpp) (lines 94-108 for level parsing).*

### C++ API Integration

```cpp
#include "kanzi/api/Compressor.hpp"
#include "kanzi/util/Context.hpp"

int main() {
    kanzi::Context ctx;
    ctx.putInt("level", 6);          // Select level 6 preset
    ctx.putInt("jobs", 2);           // Enable 2-thread parallelism
    ctx.putString("inputName",  "data.bin");
    ctx.putString("outputName", "data.knz");

    kanzi::Compressor comp(ctx);    // Selects transform & codec internally
    uint64 written = 0;
    comp.compress(written);         // Returns compressed size in bytes
}

```

*The `Compressor` constructor (in [`src/api/Compressor.hpp/.cpp`](https://github.com/flanglet/kanzi-cpp/blob/main/src/api/Compressor.hpp/.cpp)) forwards the context to `BlockCompressor`, which invokes `getTransformAndCodec`. The level value is retrieved via `ctx.getInt("level")` as seen in `BlockCompressor::BlockCompressor`.*

### Custom Pipeline Override

```cpp
kanzi::Context ctx;
ctx.putString("transform", "TEXT+UTF+BWT+RANK+ZRLT"); // Custom pipeline
ctx.putString("entropy",   "ANS0");                 // Custom codec
// No level set - BlockCompressor skips getTransformAndCodec()
kanzi::Compressor comp(ctx);

```

*When `level` is omitted, `BlockCompressor` falls back to the custom strings (see lines 60-74 of [`BlockCompressor.cpp`](https://github.com/flanglet/kanzi-cpp/blob/main/BlockCompressor.cpp)).*

## Summary

- **Kanzi compression levels 0-9** are hard-coded presets in `BlockCompressor::getTransformAndCodec` that pair specific transform pipelines with entropy codecs.
- **Level 0** provides pass-through storage, while **level 9** employs the most aggressive `EXE+RLT+TEXT+UTF+DNA` transform with `TPAQX` entropy coding for maximum compression.
- **Level 3** serves as the default, offering a balance between the `TEXT+UTF+PACK+MM+LZX` transform and fast `HUFFMAN` coding.
- **Memory usage** scales with level due to BWT buffers and context-modeling requirements; levels 0-3 remain lightweight while levels 8-9 require substantial RAM.
- **Custom pipelines** bypass the level system entirely by setting `--transform` and `--entropy` directly in the API or CLI.

## Frequently Asked Questions

### What is the default Kanzi compression level?

The default level is **3**. When you run `kanzi -c -i input -o output` without specifying `-l`, the application automatically selects level 3, which uses the `TEXT+UTF+PACK+MM+LZX` transform pipeline paired with `HUFFMAN` entropy coding. This preset targets general-purpose files such as text documents and executables while maintaining approximately 10% of the compression time required by level 9.

### How do Kanzi compression levels affect memory usage?

Memory consumption increases with compression level primarily due to transform complexity and entropy codec state. Levels 0-3 typically require less than 50 MiB because they use simple LZ variants or no transforms and lightweight codecs like `HUFFMAN` or `NONE`. Levels 5-7 allocate additional buffers for the Burrows-Wheeler Transform (BWT), while levels 8-9 require substantial memory for context-mixing models (`TPAQ`/`TPAQX`) and multiple transform stages including `EXE` and `RLT` filters.

### Can I use custom transforms instead of the preset levels?

Yes. You can bypass the level system entirely by specifying the `--transform` and `--entropy` arguments directly via CLI, or by calling `ctx.putString("transform", ...)` and `ctx.putString("entropy", ...)` in the C++ API. When these strings are provided, `BlockCompressor` skips the `getTransformAndCodec` lookup and uses your custom pipeline. This allows experimentation with combinations not covered by the standard 0-9 presets, such as `TEXT+UTF+BWT+RANK+ZRLT` with `ANS0`.

### What is the performance difference between level 1 and level 9?

Level 1 is approximately 160× faster than level 9 while providing minimal compression. According to benchmark data in the repository README, compressing the *silesia.tar* corpus takes roughly 72 ms at level 1 versus 11,618 ms at level 9. Level 1 uses only the `LZX` transform with no entropy codec, making it suitable for real-time streaming, while level 9 employs the full `EXE+RLT+TEXT+UTF+DNA` transform chain with the `TPAQX` codec for maximum compression ratio.