Skip to content

Reuse the ZSTD context and skip compressing all-zero samples in CompressionAnalyzer. - #999

Draft
copybara-service[bot] wants to merge 1 commit into
masterfrom
test_983583135
Draft

copybara-service[bot] wants to merge 1 commit into
masterfrom
test_983583135

Conversation

@copybara-service

Copy link
Copy Markdown

Reuse the ZSTD context and skip compressing all-zero samples in CompressionAnalyzer.

ZSTD_compress() builds and tears down a full compression context on every
call: at level 1 that is a ~1 MiB workspace malloc'd and freed through the page
heap once per sampled allocation while building a heap profile. Create one
ZSTD_CCtx per CompressionAnalyzer and drive it with ZSTD_compressCCtx(), which
mirrors ZSTD_compress() semantics (explicit level, no sticky parameters) so
compressed byte counts are unchanged. An instance was already single-use
scratch state (local_copy_, compress_buf_) and profile_builder walks samples
serially with one instance; the class is now non-copyable.

Count zero bytes a uint64_t at a time (SWAR zero-lane mask + popcount) instead
of absl::c_count, which clang did not vectorize (~2.4 GiB/s). An all-zero
word costs one load+compare, so all-zero samples scan at ~15 GiB/s and mixed
data at 4-7 GiB/s. The count doubles as the all-zero test: such samples skip
ZSTD entirely and report compressed_size = 0. Previously they reported only
ZSTD framing overhead (~11 bytes for 8 KiB, ~73 bytes for 2 MiB, scaled), so
the estimate differs by at most 0.004% of the sample; zero_bytes is identical.

…essionAnalyzer.

ZSTD_compress() builds and tears down a full compression context on every
call: at level 1 that is a ~1 MiB workspace malloc'd and freed through the page
heap once per sampled allocation while building a heap profile.  Create one
ZSTD_CCtx per CompressionAnalyzer and drive it with ZSTD_compressCCtx(), which
mirrors ZSTD_compress() semantics (explicit level, no sticky parameters) so
compressed byte counts are unchanged.  An instance was already single-use
scratch state (local_copy_, compress_buf_) and profile_builder walks samples
serially with one instance; the class is now non-copyable.

Count zero bytes a uint64_t at a time (SWAR zero-lane mask + popcount) instead
of absl::c_count, which clang did not vectorize (~2.4 GiB/s).  An all-zero
word costs one load+compare, so all-zero samples scan at ~15 GiB/s and mixed
data at 4-7 GiB/s.  The count doubles as the all-zero test: such samples skip
ZSTD entirely and report compressed_size = 0.  Previously they reported only
ZSTD framing overhead (~11 bytes for 8 KiB, ~73 bytes for 2 MiB, scaled), so
the estimate differs by at most 0.004% of the sample; zero_bytes is identical.

PiperOrigin-RevId: 983583135
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