mirror of
https://github.com/kvcache-ai/AgentENV.git
synced 2026-11-05 01:17:36 +00:00
[PR #92] [MERGED] feat(sandbox): add optional ZFile compression for memory snapshots #175
Labels
No labels
bug
documentation
enhancement
enhancement
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/AgentENV#175
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/kvcache-ai/AgentENV/pull/92
Author: @huajq
Created: 7/31/2026
Status: ✅ Merged
Merged: 8/4/2026
Merged by: @yingdi-shan
Base:
main← Head:zfile📝 Commits (3)
a7f24b4feat(sandbox): add optional ZFile compression for memory snapshotsccbae02feat(overlaybd): add persistent worker pool and sync pwrite for ZFile compression4b7501dtest(sandbox): add memory snapshot compression integration tests📊 Changes
22 files changed (+2072 additions, -796 deletions)
View changed files
📝
Cargo.lock(+2 -16)📝
config/default.toml(+5 -0)📝
config/oss_default.toml(+5 -0)📝
crates/e2e-tests/Cargo.toml(+1 -0)📝
crates/e2e-tests/tests/snapshot_oss_e2e_test.rs(+69 -6)📝
docs/src/configuration/reference.md(+2 -0)📝
src/cfg.rs(+64 -0)📝
src/sandbox/firecracker/overlaybd_snapshot.rs(+241 -50)📝
src/sandbox/firecracker/sandbox.rs(+20 -9)📝
src/sandbox/ublk/mod.rs(+3 -1)📝
src/sandbox/ublk/overlaybd.rs(+284 -12)📝
src/snapshot/repository/backends/posixfs/artifacts.rs(+114 -0)📝
storage/overlaybd/Cargo.toml(+2 -1)📝
storage/overlaybd/src/backend/local.rs(+48 -0)📝
storage/overlaybd/src/compression/zfile.rs(+941 -638)📝
storage/overlaybd/src/dense_export.rs(+4 -0)📝
storage/overlaybd/src/io/virtual_file.rs(+8 -0)📝
storage/overlaybd/src/lsmt/file/helper.rs(+74 -29)📝
storage/overlaybd/src/tools/mod.rs(+3 -1)📝
storage/overlaybd/src/tools/packaging.rs(+26 -19)...and 2 more files
📄 Description
What
Add optional ZFile compression support for Firecracker memory snapshots. When enabled, dirty memory pages are compressed during snapshot creation using LZ4 (default) or Zstd, reducing snapshot artifact size by ~70-88% at the cost of ~40-90% longer pause latency.
Why
Memory snapshots for large VMs produce multi-GB artifacts. Compressing them during creation reduces storage and transfer costs, which is especially valuable for snapshot templates shared across nodes.
Related issue
Closes #
Scope and non-goals
Included:
[memory_snapshot]config:compression_enabled(default false),compression_algorithm(lz4/zstd),compression_workers(default 1, max 64)ProcessVmReader(process_vm_readv) →compact_to→ raw orZFileCompactWriter→ temp → renameWorkerPool(std::thread + crossbeam-channel),CompressedSegment(contiguous output, no per-block Vec), 512 KiB compression batch, ordered committer, cancellation-safe poisoningLocalFile::write_at_sync_pwritefor >4KiB batches (bypasses io_uring overhead on local page-cache writes)compact_toordered writer support, zeroed-index sort fix (Critical), MAX_LENGTH clampExcluded:
Design and behavior changes
Data flow
WorkerPool architecture
Key design decisions
failed=true, cleared only on success; future cancellation or errors leave the writer permanently poisonedPerformance (1 GiB structured text payload, 1536 MiB VM)
LZ4 compression adds ~40% pause latency for ~70% size reduction. Zstd adds ~90% for ~88% reduction.
Zeroed-index sort fix (Critical bug fix included)
compact_topreviously pushed zeroedSegmentMappingentries intocompact_indexduring phase 1, then appended data entries in phase 2. This produced an unsorted index ([all zeros..., all data...]), causingpartition_pointlookups inReadOnlyIndexto silently miss mappings and read committed data as zeros. Fixed by sortingcompact_indexbeforecompress_raw_index.Compatibility and operations
[memory_snapshot]keys with safe defaults (disabled, lz4, 1 worker)crossbeam-channeldependency. No new system requirements.Validation
make fmt(cargo fmt --all -- --check)make clippy(cargo clippy -p overlaybd -p agentenv --all-targets -- -D warnings, zero warnings)make test-unit(overlaybd lib 304/0/1 ignored, agentenv 6 core tests 6/6)make -C services test(N/A, no services/ changes)maketarget (N/A, no generated code changes)Commands and results:
Skipped checks and reasons:
make -C services test: noservices/changesRisks and reviewer notes
Correctness:
.await, so cancellation cannot strand stale results. Worker panics are caught viacatch_unwindand converted to per-seq errors.test_verify_builderasserts workers=4 vs workers=1 produce identical files.Performance:
pool.recv()blocks the calling Tokio task for up to one 512 KiB batch compression time (~ms). This is bounded and documented with a TODO to wrap inspawn_blockingif latency-sensitive.process_vm_readvremains synchronous on the Tokio worker thread (existing TODO). Raw pause is unaffected; compression pause is dominated by codec CPU.Compatibility:
lz4_flextolz4-sys(C liblz4). Both produce standard LZ4 block format; old layers remain readable. Content-addressed caches may see different digests for the same input (LZ4 output is not canonical).compression_workersis clamped to [1, 64] to prevent absurd configs from spawning excessive OS threads.Key files for review:
storage/overlaybd/src/compression/zfile.rs(WorkerPool, CompressedSegment, commit_compressed_batch, tests)src/sandbox/firecracker/overlaybd_snapshot.rs(direct memory snapshot)src/sandbox/ublk/overlaybd.rs(compression config routing)storage/overlaybd/src/lsmt/file/helper.rs(compact_to ordered writer, zeroed-index fix)storage/overlaybd/src/backend/local.rs(write_at_sync_pwrite)Checklist
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.