mirror of
https://github.com/kvcache-ai/AgentENV.git
synced 2026-11-05 01:17:36 +00:00
[GH-ISSUE #215] Cold rootfs metadata IO dominates first-command latency on freshly-booted sandboxes — expose a warm-up path #69
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#69
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?
Originally created by @dushulin on GitHub (Aug 25, 2026).
Original GitHub issue: https://github.com/kvcache-ai/AgentENV/issues/215
Summary
On a freshly booted sandbox whose overlaybd rootfs is cold on the local node (registryfs backend, block cache empty, any registry-mirror / P2P upstream may or may not be warm), the first metadata-heavy workspace scan run from inside the guest takes ~2 orders of magnitude longer than the same command re-run seconds later in the same sandbox.
By "metadata-heavy workspace scan" we mean anything that has to stat/open a large fraction of the application checkout and its VCS working directory: a full tree walk, a full diff against HEAD, a full clean pass, etc. — the workloads a batch of AI-agent rollouts routinely emit as their very first step per sandbox.
In a rollout-style eval (many short-lived sandboxes, one first-step scan each) this single class of first-time operation is the dominant driver of per-command wall-clock budget overruns, even when no individual command's logical work should exceed that budget on a bare Linux host.
Reproduction sketch
The ratio, on our NVMe-backed nodes with a warm registry-mirror upstream but an empty local overlaybd block cache, is a two-digit multiplier.
Where the time goes (from instrumenting the cold path)
Two structural properties, not an obviously-fixable hot path:
PrefetchConfig.concurrencyexists (default 16) but is only used when a trace-based prefetcher is active.Once the metadata blocks land in the guest kernel page cache, the second run has ~no IO to do. The problem is that nothing pulls ahead of the guest during the first run.
What already exists in-tree but is not wired
The overlaybd code already ships the trace-prefetch primitive under
storage/overlaybd/src/prefetch.rs(PrefetchMode::Record | Replay | Disabled), matching the design containerd/accelerated-container-image uses. On our reading ofstorage/overlaybd/src/image/image_file.rs::init_image_file(around L322–L340), the prefetcher is only constructed when the image config declaresacceleration_layeror when arecord_trace_pathfile already exists on disk. Neither is produced by the sandbox launch path today, so this code effectively never runs in production.Separately, Firecracker
Diffsnapshot / resume already preserves the guest kernel page cache across pause / resume — so a deliberate "boot → warm → pause → publish, later resume users into it" pipeline would sidestep the cold path entirely for on-node warm resumes. Nothing in the current template-builder flow does this as a warm-up step.Ask
We would like guidance on which direction upstream considers the right long-term fix, so we can contribute rather than fork:
Happy to run measurements against any candidate patch on the same workload if that is useful, and to prototype (1) if the direction is agreed.
@dushulin commented on GitHub (Aug 25, 2026):
cc @LSX-s-Software @yingdi-shan Do you have any experience solving, or any recommended approaches for, this kind of metadata access scenario (e.g. find / or rm -rf node cache)? Or do you have any related plans going forward to optimize the performance of system metadata access storms?
@yingdi-shan commented on GitHub (Aug 25, 2026):
Thanks for the detailed investigation. Our current recommendations are:
If many sandboxes will use the same set of workspace, boot the template, run a representative workspace scan, and immediately take a snapshot. The guest page cache is then preserved in the snapshot, so subsequent sandboxes created from it should avoid most of the cold metadata path and be much more efficient. You can also tune the guest DAMON reclaim settings, especially by increasing
damon_reclaim.min_age, to keep page-cache pages resident longer. Turn on the memory compression can furthur increase the performance on slow network, at the cost of more CPU cycles.Keep the object storage and AgentENV nodes in the same low-latency network whenever possible. Another option is to host object storage close to the nodes yourself using MinIO.
Enabling background download and P2P can improve performance, but the current P2P implementation is not mature yet, so it should be evaluated carefully before relying on it in production.
@dushulin commented on GitHub (Aug 26, 2026):
Thank you for your reply. @yingdi-shan
We mainly use it for reinforcement learning (RL) training, so each environment is different. We use the cold-sandbox interface for cold start and do not use a template path.
In addition, we have integrated Dragonfly's P2P cluster (the same cluster as agentenv) to accelerate pulling of OBD images.
In our scenario, when the model solves problems it also generates some metadata access requests such as
find, and the access paths are not fixed. Is there a way to optimize for this kind of scenario?@yingdi-shan commented on GitHub (Aug 26, 2026):
In our use cases, the data/workspace is mounted through the extra-drive interface (we're adding a volume API in PR #214). In this scenario, the cache hit rate can be high since many sandboxes share the same block cache, which makes the problem less severe.
@cheney-xiaobo commented on GitHub (Aug 27, 2026):
In the AgentENV scenario, why not directly use an existing P2P framework like Dragonfly? What unique design considerations led to building a custom P2P framework instead?
@yingdi-shan commented on GitHub (Aug 27, 2026):
See issue #12 for more context. The main driver is instant snapshotting: we want snapshots to be usable immediately, without waiting for an upload to object storage to complete. Achieving that requires tightly coupling AENV's garbage collection with the P2P layer itself, something a general-purpose, standalone P2P framework isn't designed to support.
Besides, we're not building a P2P framework entirely from scratch. We use Iroh as the underlying P2P layer rather than reinventing that layer.