How Do Zstd Compression Strategies Affect Performance? A Technical Guide to the 9 Algorithmic Levels

Zstd compression strategies range from ZSTD_fast (1) for ultra-low latency to ZSTD_btultra2 (9) for maximum compression ratio, with each strategy implementing distinct match-finding algorithms that trade CPU cycles for storage efficiency.

In the facebook/zstd repository, compression strategies control the core algorithmic approach used to identify and encode repeated data patterns. Defined in lib/zstd.h, these nine strategies determine whether the compressor utilizes simple hash tables, chained probing, or exhaustive binary-tree searches, directly impacting both memory consumption and throughput.

The Nine Zstd Compression Strategies Explained

The ZSTD_strategy enum in lib/zstd.h (lines 35-45) defines nine numeric strategies ordered from fastest to strongest:

  1. ZSTD_fast (1) – Uses only a primary hash table with no secondary structures.
  2. ZSTD_dfast (2) – Adds a secondary "chain" table for limited probing.
  3. ZSTD_greedy (3) – Performs a single search per position.
  4. ZSTD_lazy (4) – Re-searches a position if a longer match is possible.
  5. ZSTD_lazy2 (5) – Two-pass lazy search allowing deeper exploration (implemented in lib/compress/zstd_opt.c).
  6. ZSTD_btlazy2 (6) – Binary-tree lazy search with two-pass evaluation.
  7. ZSTD_btopt (7) – Optimized binary-tree search using a single pass.
  8. ZSTD_btultra (8) – Exhaustive binary-tree search with higher depth.
  9. ZSTD_btultra2 (9) – Most exhaustive search with highest tree depth.

As the strategy number increases, the algorithm shifts from simple hashing to complex tree traversals, increasing CPU usage while improving compression ratio.

Performance and Compression Ratio Trade-offs

ZSTD_fast delivers ultra-fast compression with minimal CPU usage by relying solely on primary hash table lookups. It yields the lowest compression ratio but maintains the highest throughput, making it ideal for real-time logging and low-latency pipelines.

ZSTD_dfast introduces a secondary chain table, providing slightly better compression than ZSTD_fast while remaining in the ultra-fast category. The added probing mechanism consumes marginally more CPU but detects more pattern repetitions.

ZSTD_greedy marks the transition to moderate complexity, performing a single search per position. This strategy balances speed and ratio for general-purpose workloads that cannot tolerate the latency of tree-based searches.

ZSTD_lazy and ZSTD_lazy2 implement re-searching logic that evaluates whether longer matches exist at each position. ZSTD_lazy2 particularly utilizes the two-pass strategy selection logic found in lib/compress/zstd_opt.c, reducing speed further but achieving noticeable ratio improvements over greedy approaches.

ZSTD_btlazy2, ZSTD_btopt, ZSTD_btultra, and ZSTD_btultra2 employ binary-tree structures for match finding. These strategies require additional memory for tree maintenance and exhibit progressively slower compression speeds. ZSTD_btopt (strategy 7) typically offers the best speed-to-compression balance, while ZSTD_btultra2 (strategy 9) provides the highest possible compression ratio at the cost of significant CPU and memory overhead, as it performs the most exhaustive searches with the deepest tree traversals.

Advanced Parameters That Interact With Strategies

The effectiveness of advanced compression parameters varies significantly across zstd compression strategies:

  • hashLog – Controls the size of the primary hash table. Larger values accelerate all strategies but provide disproportionate benefits to faster strategies like ZSTD_fast.

  • chainLog – Determines the size of the secondary probe structure. This parameter is ignored for ZSTD_fast but becomes crucial for ZSTD_dfast and chain-dependent strategies.

  • searchLog, minMatch, and targetLength – Govern the depth and breadth of match searching. These parameters grow increasingly relevant as strategies approach the bt* family.

Notably, targetLength exhibits reversed behavioral effects between strategy families. According to programs/zstd.1.md (lines 74-80), larger targetLength values increase speed for ZSTD_fast while improving compression ratio for binary-tree strategies (bt* family). The compressor dynamically selects optimal defaults for these parameters based on the chosen compression level and source size, as implemented in lib/zstd.h (lines 68-102).

Implementing Zstd Compression Strategies

Command Line Interface

The zstd CLI exposes strategy selection through the --zstd option, documented in programs/zstd.1.md (lines 71-78):


# Ultra-fast compression using strategy 1 (ZSTD_fast)

zstd -9 --zstd=strategy=1 input.txt -o output.zst

# Balanced speed/ratio using strategy 7 (ZSTD_btopt)

zstd -3 --zstd=strategy=7 input.txt -o output.zst

# Maximum compression using strategy 9 (ZSTD_btultra2)

zstd -19 --zstd=strategy=9 input.txt -o output.zst

C Library API

For programmatic control, use the advanced API defined in lib/zstd.h:

#include <zstd.h>

ZSTD_CCtx* cctx = ZSTD_createCCtx();
ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, ZSTD_btultra2); /* Strategy 9 */
size_t const result = ZSTD_compress2(cctx, dst, dstCap, src, srcSize);
ZSTD_freeCCtx(cctx);

The ZSTD_c_strategy parameter accepts any value from the ZSTD_strategy enum, allowing runtime strategy selection without recompilation.

Optimization Guidelines for Specific Workloads

For low-latency workloads such as real-time logging or network telemetry, select ZSTD_fast or ZSTD_dfast. These strategies minimize CPU blocking and maintain high throughput, particularly when combined with optimized hashLog settings.

When memory is constrained, avoid the bt* strategies (6-9). Binary-tree strategies require larger hash and chain tables, increasing heap pressure. The fast-path block-selection logic in lib/compress/zstd_preSplit.c specifically optimizes ZSTD_fast for memory-efficient operation.

For maximum compression on large archival files, ZSTD_btultra2 yields optimal ratios. This strategy interacts with long-distance matching implementations in lib/compress/zstd_ldm.c to find distant repetitions, though it requires substantial CPU resources and is unsuitable for streaming applications.

Summary

  • Zstd provides nine compression strategies (1-9) defined in lib/zstd.h, ranging from hash-based (fast) to exhaustive binary-tree (btultra2) algorithms.
  • Strategy selection directly trades speed for compression ratio: lower numbers prioritize throughput, while higher numbers maximize storage efficiency.
  • Parameter sensitivity varies by strategy: chainLog affects dfast but not fast, while targetLength reverses its effect between fast and binary-tree strategies.
  • Implementation options include the --zstd=strategy=N CLI flag and the ZSTD_CCtx_setParameter C API with ZSTD_c_strategy.
  • Workload-specific optimization requires matching strategy to constraints: use strategies 1-2 for latency, 3-5 for general-purpose, and 8-9 for archival compression.

Frequently Asked Questions

What is the default compression strategy in zstd?

The compressor dynamically selects optimal defaults based on the requested compression level and input size rather than using a single fixed strategy. According to lib/zstd.h (lines 68-102), higher compression levels automatically select deeper strategies like ZSTD_btopt or ZSTD_btultra, while lower levels default to ZSTD_fast or ZSTD_dfast.

How does the targetLength parameter behave differently across zstd compression strategies?

The targetLength parameter exhibits inverted effects depending on the strategy family. For ZSTD_fast, increasing targetLength improves compression speed by skipping short matches. Conversely, for binary-tree strategies (bt* family), larger targetLength values improve the compression ratio by allowing the algorithm to find longer, more efficient matches. This behavior is documented in programs/zstd.1.md (lines 74-80).

Can I use custom compression strategies with the zstd CLI?

Yes. The zstd command-line tool accepts strategy specifications via the --zstd=strategy=N syntax, where N is a value from 1 to 9. For example, zstd --zstd=strategy=1 selects ZSTD_fast, while zstd --zstd=strategy=9 selects ZSTD_btultra2. This functionality is documented in programs/zstd.1.md (lines 71-78).

Which zstd compression strategy offers the best balance of speed and compression?

ZSTD_btopt (strategy 7) typically provides the optimal trade-off for general-purpose workloads, offering significant compression improvements over lazy strategies while maintaining reasonable CPU usage. For applications where speed is paramount, ZSTD_dfast (strategy 2) offers a compromise between the minimal overhead of ZSTD_fast and the improved ratio of greedy approaches.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →