mirror of
https://github.com/kvcache-ai/AgentENV.git
synced 2026-11-05 01:17:36 +00:00
[PR #314] [MERGED] feat(snapshot): add startup manifest prefetch for POSIX snapshots #338
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#338
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/314
Author: @Hygge-Gezelligheid
Created: 9/22/2026
Status: ✅ Merged
Merged: 9/29/2026
Merged by: @yingdi-shan
Base:
main← Head:agent/posix-startup-pack📝 Commits (3)
81f27cbfeat(snapshot): record and resolve POSIX startup manifestscfa561afeat(snapshot): prefetch POSIX startup through shared memory devices9ce53f8test(snapshot): validate and document POSIX startup prefetch📊 Changes
17 files changed (+2433 additions, -200 deletions)
View changed files
📝
config/default.toml(+3 -3)📝
docs/src/configuration/reference.md(+38 -0)➕
scripts/verify-posix-startup-pack-smoke.py(+108 -0)📝
src/sandbox/firecracker/sandbox.rs(+77 -22)📝
src/sandbox/firecracker/startup_pack.rs(+1119 -13)📝
src/sandbox/manifest.rs(+2 -2)📝
src/sandbox/ublk/device.rs(+10 -2)📝
src/snapshot/manager.rs(+7 -6)📝
src/snapshot/mod.rs(+2 -2)📝
src/snapshot/repository/backends/oss/repository.rs(+99 -71)📝
src/snapshot/repository/backends/posixfs/backend.rs(+259 -4)📝
src/snapshot/repository/backends/posixfs/catalog.rs(+232 -6)📝
src/snapshot/repository/backends/posixfs/runtime.rs(+33 -1)📝
src/snapshot/startup_pack.rs(+303 -65)📝
src/snapshot/types/snapshot.rs(+3 -3)📝
tests/integration.rs(+3 -0)➕
tests/integration/posix_startup_pack.rs(+135 -0)📄 Description
Overview
Extend the startup memory manifest flow from PR #298 to POSIX snapshots. The capture and publication stages asynchronously save the startup manifest. During restore, the logical memory ranges in the manifest are prefetched through the same memory ublk device that Firecracker actually uses.
Recording and consumption are disabled by default, and the OSS prefetch path remains unchanged.
Implementation
LocalPath, validate their size, hash, and memory layout, then perform buffered device reads concurrently with restore.io_engine = 2, for which device prefetch has not yet been validated; leave the existing I/O engine settings unchanged.No separate disk cache, whole-layer prefetch policy, or public protocol changes are introduced. Private performance test code is not included in production changes.
Configuration
Use the existing
[snapshot.memory_startup_pack]configuration:enabled: controls recording and publication.consume_enabled: controls prefetch during restore.Both default to
false. Consumption can be disabled independently for snapshots that already contain a manifest.Validation
Performance
Experiment 1: Memory-device lifecycle; lower-file cache uncontrolled (historical)
On Madsys-4-2, five randomized blocks of serial comparisons were completed using the same native 128 MiB Ubuntu-family snapshot, release test program and daemon, and buffered-read configuration
ioEngine=0.With prefetch enabled, the mean time to ready decreased by 51.038 ms (41.3%), with improvement in all five paired blocks.
The fixed-input test follows the standard cold/hot device lifecycle and calls the normal snapshot restore path. Timing starts before the restore call and ends at envd-ready, including device acquisition, manifest validation, and prefetch work before ready. Repository resolution and baseline preparation are excluded from this interval. Cold releases the previous memory device reference; Hot retains a warm instance. No global cache clearing or lower-file cache eviction is performed, so the lower-file page cache may already be warm.
All five prefetch runs overlapped with VM restore and completed before ready. From the observation point after device acquisition to the read-drain observation point after ready, mean memory-device reads increased from 40.841 MiB to 56.505 MiB, an increase of approximately 38.4%. These are device-level counters, not physical disk reads or exact guest page-fault counts.
Experiment 2: Controlled memory lower-file page cache (current head)
This extension measures how the host Linux page cache of the snapshot's memory lower file changes restore latency and the benefit of startup prefetch. It tests commit
8a16c6f7d80d92fbb774ca0ac597918f5aafc09don Madsys-4-2, using the same fixed one-vCPU, 128 MiB Ubuntu-family POSIX snapshot and buffered I/O configurationioEngine=0.Each of eight blocks contains four serial restores in a frozen randomized order: file-warm/prefetch-off, file-warm/prefetch-on, file-cold/prefetch-off, and file-cold/prefetch-on. All 32 formal restores and all block admission/exit checks passed; four pilot restores are excluded, and neither reserve block was needed.
Cache preparation and verification: All four conditions first perform an untimed, prefetch-off baseline restore, then stop it and wait for acknowledgement that its memory-device reference has been released. All four timed restores therefore use the device-cold lifecycle; “file-warm” does not mean a warm VM or the hot control from Experiment 1. After baseline release, both treatments fully read and SHA-256-check a new, independently copied memory lower file. File-warm retains those cached pages. File-cold applies one
POSIX_FADV_DONTNEEDoperation only to that private file. Immediately before timing,mincoremust show 14,472/14,472 resident pages for file-warm or 0/14,472 for file-cold; every formal trial met its threshold. The file is 59,277,312 bytes, with 4,096-byte host pages. The final residency probe is outside the timer, with a recorded probe-to-timer gap of at most 1 microsecond. No file-content read or diagnostic I/O occurs in that gap. No global cache clearing or changes to other users' files, services, or devices are performed.Timing scope: Timing starts immediately before the normal restore constructor and
start(), and ends whenstart()returns at envd-ready. Memory-device acquisition, manifest validation, prefetch, VM restore, and guest readiness are included. Repository resolution, the baseline restore/release, file hashing, cache preparation, and the final pre-timer residency probe are excluded. Each trial has its own process and private runtime; both baseline and timed memory-device releases are acknowledged, and final checks show no remaining experiment processes or Unix sockets.Paired differences are calculated within each block. The intervals below are descriptive 95% Student-t intervals over eight paired differences (7 degrees of freedom):
Prefetch is faster in all eight pairs under each file-cache condition. These measurements support a substantial benefit for this fixed snapshot when its memory lower-file pages are initially absent from the host page cache, and show that the file-cache state materially affects measured restore latency.
Scope of “file-cold”: Only this memory lower file's Linux page-cache residency is controlled. Rootfs file pages, filesystem metadata, process state, and NVMe controller/SSD caches may remain warm. This measures snapshot restore to envd-ready, rather than Ubuntu boot from scratch or the entire user-request-to-ready path. Logical ublk counters are not physical disk traffic or guest page-fault counts; post-ready residency and counters have their own observation timestamps. Experiments 1 and 2 use different measurement builds and cache treatments, and their samples are reported separately.
Limitations
Prefetch competes with on-demand reads for CPU, cache, and device bandwidth. Cancellation and timeouts can prevent subsequent reads but cannot interrupt reads already blocked in the kernel. Such reads may delay final device release; the VM is requested to stop before waiting.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.