No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-06 08:07:08 +00:00
.github/workflows ci: add cleanup step for test binaries in release workflow 2026-07-27 04:56:39 +02:00
cmd Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
testdata/bench Initial commit 2026-03-31 09:03:00 +02:00
.gitignore ci: add PGO profile generation step to release workflow 2026-07-27 04:52:29 +02:00
.golangci.yml upgrade 2026-05-31 15:48:22 +02:00
.goreleaser.yaml feat: support tar.gz archives for Linux and macOS; add extraction logic and tests 2026-04-08 10:36:21 +02:00
benchmark_test.go Performance improvements 2026-07-27 04:43:25 +02:00
blocksplitter.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
cache.go Performance improvements 2026-07-27 04:43:25 +02:00
cache_integration_test.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
deflate.go reduce LZ77 token buffer allocations 2026-09-06 10:03:37 +02:00
go.mod upgrade 2026-09-03 20:41:16 +02:00
gzip_container.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
hash.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
katajainen.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
katajainen_test.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
lz77.go reduce LZ77 token buffer allocations 2026-09-06 10:03:37 +02:00
lz77_optimization_test.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
optimization_test.go Performance improvements 2026-07-27 04:43:25 +02:00
README.md docs: update benchmark summary 2026-09-06 08:07:08 +00:00
scratch.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
squeeze.go reduce LZ77 token buffer allocations 2026-09-06 10:03:37 +02:00
symbols.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
Taskfile.yml upgrade 2026-09-04 16:02:34 +02:00
tree.go feat: add zopfli-go CLI with support for gzip compression 2026-04-08 08:39:03 +02:00
util.go feat: add zopfli-go CLI with support for gzip compression 2026-04-08 08:39:03 +02:00
zlib_container.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
zopfli.go Add comprehensive tests for Zopfli compression algorithms 2026-07-10 07:34:40 +02:00
zopfli_test.go feat: add zopfli-go CLI with support for gzip compression 2026-04-08 08:39:03 +02:00

zopfli-go

zopfli-go is a pure Go implementation of Zopfli-style compression for gzip, zlib, and raw deflate output.

Go Usage

package main

import zopfli "github.com/ralscha/zopfli-go"

func main() {
	compressed := zopfli.Gzip([]byte("hello, world"))
}

For custom tuning, use DefaultOptions() and call Compress with FormatGzip, FormatZlib, or FormatDeflate.

package main

import zopfli "github.com/ralscha/zopfli-go"

func main() {
	options := zopfli.DefaultOptions()
	options.NumIterations = 5
	options.BlockSplittingMax = 8

	compressed := zopfli.CompressParallel(&options, zopfli.FormatGzip, []byte("hello, tuned world"), 4)
}

Fast profile

FastOptions() starts with DefaultOptions() and changes exactly one setting: NumIterations is reduced from 15 to 3.

Setting Default Fast
Optimal parsing iterations 15 3
Block splitting enabled enabled
Maximum split points 15 15

Fewer parsing iterations reduce CPU time, but can produce a slightly larger compressed file because fewer candidate parses are evaluated. The output is still a normal, deterministic gzip, zlib, or deflate stream. Fast mode does not enable parallelism; use CompressParallel or CLI --workers-per-file separately when compressing a large input.

options := zopfli.FastOptions()
compressed := zopfli.Compress(&options, zopfli.FormatGzip, data)

The CLI --fast flag applies the same three-iteration profile. Explicit --iterations, --block-splitting, and --block-splitting-max flags take precedence over the profile.

Compress is serial. CompressParallel bounds parallel analysis inside one file; keep its worker count at 1 when compressing many files concurrently, or increase it for a small number of large inputs. Worker counts are capped at MaxCompressionWorkers (currently 4). For each active 1 MiB input block, the match cache uses about 12 MiB of metadata plus 4 bytes per cached distance run, with a 60 MiB hard ceiling; parsing and token buffers require additional memory. The CLI divides its default --jobs value by --workers-per-file so the two levels of concurrency do not multiply by default; an explicit --jobs value overrides that safeguard.

CLI Usage

The repository includes a file-oriented CLI for precompressing web assets into adjacent .gz files.

./zopfli-go --help
./zopfli-go --jobs 8 public
./zopfli-go --fast public
./zopfli-go --fast --jobs 1 --workers-per-file 4 large-asset.js
./zopfli-go --include-suffix .js --exclude-suffix .min.js public
./zopfli-go public assets/app.js
./zopfli-go --json public

Behavior:

  • File and directory inputs are accepted.
  • Directories are walked recursively.
  • Outputs are written next to the source file as filename.ext.gz.
  • Files are skipped when the .gz output is larger than or equal to the original.
  • When a file is skipped for size, any stale adjacent .gz output from an earlier run is removed.
  • Existing .gz files are ignored as inputs unless --allow-gzip-inputs is set.

Supported CLI flags:

  • -j, --jobs
  • --fast
  • -i, --include-suffix and -x, --exclude-suffix (repeatable, matched against relative paths or base filenames)
  • --allow-gzip-inputs
  • -n, --iterations
  • --workers-per-file
  • --block-splitting
  • --block-splitting-last=false|true|both (deprecated compatibility option)
  • --block-splitting-max
  • -v, --verbose
  • -V, --verbose-more
  • -J, --json

Benchmarks

The table below is updated by the benchmark workflow on branch pushes and workflow dispatches.

Benchmark comparisons use the original upstream Zopfli implementation from https://github.com/google/zopfli.

Corpus GoMs PgoMs CMs PGO/Go Go/C PGO/C GoBytes CBytes GzipBytes
mixed-256k 2217.50 2193.99 7609.87 0.99 0.29 0.29 3162 3162 3201
random-256k 173.49 155.67 367.27 0.90 0.47 0.42 262183 262183 262204
real-files-256k 765.32 704.55 2573.09 0.92 0.30 0.27 4649 4649 5033
records-logs-256k 854.94 803.30 2233.16 0.94 0.38 0.36 2510 2510 2661
tiny-text 14.23 15.67 31.19 1.10 0.46 0.50 58 58 62
web-assets-256k 755.25 695.70 2337.14 0.92 0.32 0.30 3756 3756 4073

Development

Use the Go version declared in go.mod.

Run the package tests with:

go test ./...

Generate the benchmark summary locally with:

go run ./cmd/zopfli-task bench-summary

Releases

GitHub releases are produced by GoReleaser from version tags such as v1.0.0.

Release assets are archived as .tar.gz on Linux and macOS, and as .zip on Windows.

Those release assets are consumed directly by bread-compressor-cli when its --use-zopfli-go flag is enabled.