Repository navigation
Conversation
Template materialization computes the compressed rootfs SHA-256 inline in the zstd decoder's reads. Once the expanded image is hashed with BLAKE3, the decoder thread is the slowest stage: on the Oct 20 r6id.metal fixture (6.44 GB compressed, 24 GiB logical) it used 12.6 CPU-seconds of a 16.0-second materialization and never waited for a free buffer, and the compressed SHA-256 accounted for about 4.75 of those seconds. The sparse writer, the next stage, used 7.5. The decoder now reads the compressed file into a pool of three 8 MiB buffers. Each filled buffer is shared with a dedicated thread that computes the same SHA-256 and returns the buffer to the pool, so hashing overlaps decoding, and a slow hash makes reads wait rather than grow memory. The digest, its format, where it is compared and the mismatch handling are unchanged. The input pool uses 24 MiB per materialization instead of one 8 MiB read buffer. Expected effect, projected from the stage CPU above rather than measured on that worker: - Releases with BLAKE3 identities: materialization of about 16 s falls to about 11-12 s, limited by the decoder without the hash (about 7.8 s) and the sparse writer (about 7.5 s). That is roughly 0.75 s per compressed GB on cold template pulls, prefetches and compressed imports. - Releases with SHA-256 identities, which today are all of them: little or no change, because the expanded SHA-256 thread is the bottleneck there and the decoder already waited 7.7 s for buffers. - Sandbox snapshot restores are unaffected; they do not use this path. Total CPU per materialization is unchanged; one more thread runs during it. Validation: the 255 template-manager tests pass, including a new test that reads input through one-byte to larger-than-input buffers, with short reads and recycled pools, and checks the delivered bytes and digest against SHA-256 of the whole input. Clippy is clean. A local interleaved A/B on Apple silicon (12 GiB logical, 3.2 GB compressed, four runs each) produced identical, independently verified compressed digests, with materialization 4.5% faster for SHA-256 identities and 0.9% faster for BLAKE3 identities. That machine's SHA-256 hardware leaves the expanded hash as its bottleneck in both cases, so it confirms correctness and no regression, not the projected x86 gain.
nickdujay-pplx
left a comment
There was a problem hiding this comment.
Reviewed buffer ownership, backpressure, thread shutdown, digest verification, publication order, and rollback compatibility. The input pool is bounded, chunks are shared without another byte copy, and existing artifact formats and verification remain unchanged.
All 255 template-manager tests passed locally. Additional checks of the extracted reader verified bytes/digests across pool depths and 150 early drops. Approving with two non-blocking follow-ups: measure the target-architecture benefit under concurrent materialization, and retain EOF state in the private reader. The repeated-EOF issue is not reached by the current zstd call path.
|
|
||
| const ROOTFS_SPARSE_BLOCK_BYTES: usize = 64 * 1024; | ||
| const COMPRESSED_INPUT_BUFFER_SIZE: usize = 8 * 1024 * 1024; | ||
| const COMPRESSED_INPUT_PIPELINE_DEPTH: usize = 3; |
There was a problem hiding this comment.
Non-blocking performance follow-up: please add an interleaved before/after benchmark on the target CPU architecture, using a synthetic representative image and concurrent distinct-template pulls. Record wall time, CPU, and peak RSS for both digest algorithms. The fixed pool bounds this stage to 24 MiB, but the extra 16 MiB and hash thread apply per materialization; the call site also decompresses manifest entries concurrently. The overlap looks sound, but the projected decoder improvement needs that measurement before we rely on it for capacity or latency expectations.
| .as_ref() | ||
| .is_none_or(|chunk| self.position >= chunk.len); | ||
| if exhausted { | ||
| self.next_chunk()?; |
There was a problem hiding this comment.
Non-blocking reader robustness follow-up: preserve EOF without checking out another pool buffer, and add repeated-EOF coverage. I reproduced this with an empty input and depth 3: three reads return 0; the fourth blocks in free_rx.recv(). An empty chunk is not sent to the hash worker, and the next fill_buf drops it, so each EOF read removes a buffer from the pool. The current zstd reader switches to its own EOF state after the first empty buffer, so this does not block the materialization path reviewed here. An EOF flag or retaining the empty current chunk would make the reader safe to reuse.
Template materialization computes the compressed rootfs SHA-256 inline in the zstd decoder's reads. Once the expanded image is hashed with BLAKE3, the decoder thread is the slowest stage: on the Oct 20 r6id.metal fixture (6.44 GB compressed, 24 GiB logical) it used 12.6 CPU-seconds of a 16.0-second materialization and never waited for a free buffer, and the compressed SHA-256 accounted for about 4.75 of those seconds. The sparse writer, the next stage, used 7.5.
The decoder now reads the compressed file into a pool of three 8 MiB buffers. Each filled buffer is shared with a dedicated thread that computes the same SHA-256 and returns the buffer to the pool, so hashing overlaps decoding, and a slow hash makes reads wait rather than grow memory. The digest, its format, where it is compared and the mismatch handling are unchanged. The input pool uses 24 MiB per materialization instead of one 8 MiB read buffer.
Expected effect, projected from the stage CPU above rather than measured on that worker:
Total CPU per materialization is unchanged; one more thread runs during it.
Validation: the 255 template-manager tests pass, including a new test that reads input through one-byte to larger-than-input buffers, with short reads and recycled pools, and checks the delivered bytes and digest against SHA-256 of the whole input. Clippy is clean. A local interleaved A/B on Apple silicon (12 GiB logical, 3.2 GB compressed, four runs each) produced identical, independently verified compressed digests, with materialization 4.5% faster for SHA-256 identities and 0.9% faster for BLAKE3 identities. That machine's SHA-256 hardware leaves the expanded hash as its bottleneck in both cases, so it confirms correctness and no regression, not the projected x86 gain.
🤖 Generated with Claude Code