perf(remote-cache): scan one level into a tar member that is itself a tar - #360
Open
raphaelvigee wants to merge 1 commit into
Open
perf(remote-cache): scan one level into a tar member that is itself a tar#360raphaelvigee wants to merge 1 commit into
raphaelvigee wants to merge 1 commit into
Conversation
… tar The content scan judges an artifact by its members' heads, which answers nothing for the shape where the artifact *wraps* another tar — an OCI bundle, a collected archive, a `.tar` a rule produced. The member's head is a tar header, no signature matches, and the whole blob is charged as compressible and gzipped anyway, which is exactly the waste the scan was added to stop. Follow one level. A member already past the size floor is now also checked for the `ustar` magic at offset 257 — the only reason the peek widens from 12 bytes to 265 — and, when it is a tar, walked with the same signature table and the same tally. No deeper. The nested walk seeks. `tar` skips by *reading* when its reader cannot seek, so handing it the member as a plain `Read` would pull the whole member through just to reach the next header; `Window` gives it a seekable view of the member's bytes instead, which is also why the descent happens after the outer walk rather than inside it (the iterator borrows the reader for as long as it lives). The early exit survives: whatever a nested walk neither credited nor rejected is charged back against the member's size before the next member is opened, so an archive of archives that is not precompressed gives up as promptly as an archive of text. A deferred member does escape the *outer* walk's early exit — its bytes are unknown until walked — but only members past MIN_MEMBER_BYTES are ever deferred, so the tiny-member case that exit was built for cannot reach the path at all. Verdict semantics are unchanged and it still never feeds a hash: the same artifact compressed or not is the same artifact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UnRHitwvHJFjDAeKef5Uwb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #356.
The waste
The content scan judges an artifact by its members' heads. That answers nothing for the shape where the artifact wraps another tar — an OCI bundle, a collected archive, a
.tara rule produced. The member's head is a tar header, no signature matches, the whole blob is charged as compressible, and it gets gzipped anyway — the exact waste #356 was added to stop, one level out of reach.The change
Contained: a member already past the size floor is now also checked for the
ustarmagic at offset 257 — the only reason the peek widens from 12 bytes to 265 — and, when it is a tar, walked with the same signature table into the same tally. One level, no deeper; a tar inside a tar inside a tar is not a shape worth the seeks. The extra copy stays where it is.Two things worth a reviewer's attention:
The nested walk seeks.
tarskips by reading when its reader can't seek, so handing it the member as a plainReadwould pull the entire member through just to reach the next header — the one thing this scan is built not to do.Windowgives it a seekable view of the member's bytes instead. That is also why the descent happens after the outer walk rather than inside it: the iterator borrows the reader for as long as it lives, so nested members are collected as(offset, size)and visited once the reader is back.The early exit survives. Whatever a nested walk neither credited nor rejected is charged back against the member's size before the next member is opened, so an archive of archives that is not precompressed gives up as promptly as an archive of text. A deferred member does escape the outer walk's early exit — its bytes are genuinely unknown until walked, and charging them beforehand would give up on precisely the archives this recursion exists to catch. Only members past
MIN_MEMBER_BYTESare ever deferred, so the tiny-member case that exit was built for cannot reach this path at all.Correctness
Verdict semantics are unchanged, and it still never feeds a hash — the same artifact compressed or not is the same artifact. Every new answer is in the safe direction on failure: a v7 tar (no magic) is not recursed into, a member that merely looks like a tar header fails to parse and is charged in full, and a nested walk that errors leaves the member charged in full. Each costs a wasted gzip at worst, which is the status quo.
Tests
Six new, all in
crates/core/src/hartifactcontent/sniff.rs:precompressed,dominant: gzip)lintclean,cargo test -p core --libgreen (145 passed).🤖 Generated with Claude Code
https://claude.ai/code/session_01UnRHitwvHJFjDAeKef5Uwb