Skip to content

feat(gix-zlib): compress with sirocco with the sirocco feature - #3127

Open
Sam Reis (srijs) wants to merge 1 commit into
GitoxideLabs:mainfrom
srijs:gix-zlib-sirocco-deflate
Open

Sam Reis (srijs) wants to merge 1 commit into
GitoxideLabs:mainfrom
srijs:gix-zlib-sirocco-deflate

Conversation

@srijs

@srijs srijs commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

This description and the change were prepared by Claude, an AI agent, working with Sam Reis (@srijs).

sirocco 0.3 adds a zlib-compatible compressor. Its levels are calibrated against zlib's: each compresses about as well as zlib's same level, in less time. This PR uses it for stream::deflate::Write when the existing sirocco feature is enabled, so gix's zlib-sirocco and gitoxide's fast features now compress with it as well as decompress.

Changes

  • gix-zlib depends on sirocco 0.3.1 (was 0.2). The decompression side's API is unchanged in 0.3; the new version only adds compression.
  • stream::deflate::Write gets a private backend: zlib-rs as before, or sirocco with the feature. Its public API doesn't change.
  • The standalone stream::deflate::Compress stays on zlib-rs, as Decompress does. It also offers a partial flush, which sirocco doesn't have.

The sirocco backend:

  • Encoder reuse: encoders are reused across writers on a thread, up to two, matched by level. An encoder's tables are about 340 KiB, and gitoxide makes a writer per object, so each writer allocating its own would dominate small objects. What a thread keeps is bounded: two encoders, plus at most 64 KiB of input buffer each.
  • Input buffering: input is buffered up to 1 MiB before compressing. Objects up to that size are compressed in one call, which lets sirocco size its tables to the object. Larger objects stream through that buffer.
  • Lifecycle: it matches zlib-rs. flush() finishes the stream; flushing again does nothing; writing again fails with the same "stream error" until reset().

Performance

These numbers compress each object of a 10% sample of git.git's objects (42,241 objects, 845 MB) with a fresh deflate::Write, as gix-pack and gix-odb do. They were measured on one thread on an Apple M4, best of 3 runs:

Level zlib-rs sirocco
1 (loose objects) 310 MB/s, 50.74% 377 MB/s, 42.52%
6 (packs) 113 MB/s, 39.92% 173 MB/s, 39.56%

At level 1 that's 22% faster, with 16% smaller loose objects. At level 6 it's 1.5x as fast, with 0.9% smaller packs. zlib-rs's level 1 compresses less than zlib's (it follows zlib-ng's fast strategy), which accounts for most of the size difference there.

Tests

The new tests in gix-zlib/tests/zlib/stream/deflate.rs hold for both backends:

  • writes after finishing fail until reset;
  • input larger than the 1 MiB buffer, in small writes and in one write;
  • writers of different levels one after another, checking the level recorded in each zlib header.

These pass with and without the feature:

  • cargo test -p gix-zlib, and with --features sirocco (as in the justfile);
  • clippy and rustdoc for gix-zlib in both configurations;
  • cargo test -p gix-odb -p gix-pack --features gix-zlib/sirocco;
  • cargo check --bin gix --no-default-features --features max-pure,fast.

On the sirocco side, the compressor is tested and fuzzed by round-tripping its output through zlib, zlib-rs, libdeflate, miniz_oxide and its own decoder, including streams with sync and full flushes.

🤖 Generated with Claude Code

https://claude.ai/code/session_0188jteQyuSCB5eSuAzNM7Lz

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-26T10:48:33.035727Z
We couldn’t complete this review. Comment @codex review to try again.
94818e4 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@srijs

srijs commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Claude, an AI agent working with Sam Reis (@srijs), here: numbers from whole gix commands, as a complement to the per-object benchmark in the description.

These compare gix built from main (9f805e2) and from this PR, both with --no-default-features --features max-pure,fast, on git.git (422,410 objects) on an Apple M4. Both builds already decompress with sirocco, so compression is the only difference. Each figure is the median of 3 runs, alternating between the builds, with the range in brackets.

Updated for sirocco 0.3.1, whose level 1 is faster and compresses more: the explode rows are from a new run. Level 6 didn't change in 0.3.1 (this PR writes a pack of exactly the same size), so the pack create rows are from the first run; a rerun alongside was disturbed by other load on the machine.

main this PR difference
gix free pack explode: writes loose objects, level 1
user CPU 63.8 s [61.6–63.8] 54.8 s [53.0–61.8] −14%
loose objects on disk 4,250,367,456 B 3,562,476,286 B −16.2%
gix free pack create: packs those loose objects, level 6
user CPU 119.2 s [118.1–120.9] 86.6 s [85.8–87.0] −27%
pack size 3,341,570,839 B 3,311,871,631 B −0.9%

Wall time doesn't improve here:

  • explode: 56–65 s for both. System time is about 140–150 s in both builds, mostly creating 422K files, and it dominates the run.
  • pack create: about 79 s for both. Compression runs on several threads, and the run is limited by something else, likely reading and decompressing the loose objects.

So for these commands on this machine the gain is CPU time and disk space rather than elapsed time.

🤖 Generated with Claude Code

`sirocco` 0.3 adds a zlib-compatible compressor whose levels compress
about as well as zlib's same level, in less time. With the feature,
`stream::deflate::Write` compresses with it; the standalone `Compress`
API stays on `zlib-rs`, as `Decompress` does.

- Encoders are reused across writers on a thread, up to two, by level:
  their tables are about 340 KiB, and a writer is made per object.
- Input is buffered up to 1 MiB, so objects up to that size are
  compressed in one call; larger ones stream through that buffer.
- Writes after `flush()` fail until `reset()`, as with `zlib-rs`.

On git.git's objects, with a writer per object as gitoxide makes them,
level 1 (loose objects) is 22% faster than `zlib-rs` with 16% smaller
output, and level 6 (packs) is 1.5x as fast with 0.9% smaller output.

The `zlib-sirocco` feature of `gix` and the `fast` feature of `gitoxide`
now compress with it too.
@srijs
Sam Reis (srijs) force-pushed the gix-zlib-sirocco-deflate branch from 94818e4 to 710cadd Compare October 26, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant