How many tool tasks fit in two cores and 2 GiB?¶
Motivation¶
When multiple Agents run together, count completed work rather than created environments. Stage and Podman reach the same tested task capacity under a shared budget, so choose between them by isolation and review needs; a VM boundary per task needs more room, and idle capacity does not predict active-task capacity.
Under a shared two-core, 2 GiB, zero-swap budget, stage and Podman complete all five rounds at 32 concurrent Python/Git tasks; pVisor VM completes all five at 16 but only three at 32. Idle probes reach 128 for stage and 64 for Podman.
These numbers and conclusions remain the original historical cohorts; the new framework has no matching rerun. See measurement coverage.
Experiment design¶
Count tasks that pass every check within a fixed cgroup budget as valid completed tasks. This count represents the valid results delivered within that budget. More completed tasks under the same budget mean higher effective capacity.
Compare native processes, pVisor stage, pVisor VM and Podman 5.8.7 on Linux/x86_64. Each batch has a fresh cgroup with a shared two-core quota, CPU 0/1 affinity, a 2 GiB memory limit and zero swap. The coordinator, payloads and helpers are inside the budget; Podman payload/conmon membership is checked. Each VM has 2 vCPU/256 MiB, still constrained by the common total budget.
Scan concurrency 1, 2, 4, 8, 16, 32, 64 and 128, with five fresh batches per cell and no warmups. Conditions are randomized within each round. All tasks wait at a stdin readiness barrier before release. Idle tasks use the same Python environment without private data or edits. Useful tasks touch and checksum all 32 MiB of private data, edit four files in a 64-file Git repository, run git status and verify all contents. Stage/VM preserve the original workspace and match results to independent Run records.
Memory is counted as whole-cgroup physical accounting, including charged page cache, kernel memory and private backing. Prepared shared tool/image caches may be charged to a parent cgroup, so this does not rank net whole-machine memory. Failed, unknown and OOM outcomes remain counted; only entirely verified, no-OOM batches enter memory/timing summaries, and slow valid samples remain. Five rounds cover this workload only: they do not establish long-term reliability or tail latency, and exclude inference, large builds and real Agent CLIs.
Data and analysis¶
Measured on 2026-10-06 local time. There are 320 batches: 263 recorded as fully passed and 57 failed; all contribute to capacity statistics. Memory is readiness-barrier memory.current P50 in MiB, from complete no-OOM batches only. “—” denotes no such batch.
Python/Git tool tasks¶
| Mode | Concurrency | Fully valid batches | Verified tasks / attempted | Unknown results | OOM batches | Barrier memory P50, MiB |
|---|---|---|---|---|---|---|
| Native process | 16 | 5/5 | 80/80 | 0 | 0 | 640.4 |
| Native process | 32 | 5/5 | 160/160 | 0 | 0 | 1268.3 |
| Native process | 64 | 0/5 | 233/320 | 0 | 5 | — |
| Native process | 128 | 0/5 | 244/640 | 0 | 5 | — |
| pVisor stage | 16 | 5/5 | 80/80 | 0 | 0 | 723.0 |
| pVisor stage | 32 | 5/5 | 160/160 | 0 | 0 | 1434.0 |
| pVisor stage | 64 | 0/5 | 204/320 | 0 | 5 | — |
| pVisor stage | 128 | 0/5 | 183/640 | 0 | 5 | — |
| pVisor VM | 16 | 5/5 | 80/80 | 0 | 0 | 2047.9 |
| pVisor VM | 32 | 3/5 | 138/160 | 0 | 0 | 2047.8 |
| pVisor VM | 64 | 0/5 | 1/320 | 0 | 0 | — |
| pVisor VM | 128 | 0/5 | 0/640 | 0 | 5 | — |
| Podman | 16 | 5/5 | 80/80 | 0 | 0 | 969.3 |
| Podman | 32 | 5/5 | 160/160 | 0 | 0 | 1931.8 |
| Podman | 64 | 0/5 | 120/320 | 64 | 5 | — |
| Podman | 128 | 0/5 | 128/640 | 128 | 5 | — |
Stage and Podman each complete 160/160 tasks at concurrency 32. Both encounter OOM at 64/128; partial completions do not establish those capacities. VM completes 138/160 tasks at 32 with only 3/5 complete batches. Launch/completion failures at higher concurrency remain visible and cannot all be attributed to OOM. Unknown results lack retained verifiable completion evidence; they are neither successes nor zero-duration tasks.
Idle environments¶
| Mode | Concurrency | Fully valid batches | Verified tasks / attempted | Unknown results | OOM batches | Barrier memory P50, MiB |
|---|---|---|---|---|---|---|
| Native process | 32 | 5/5 | 160/160 | 0 | 0 | 242.0 |
| Native process | 64 | 5/5 | 320/320 | 0 | 0 | 471.9 |
| Native process | 128 | 5/5 | 640/640 | 0 | 0 | 931.9 |
| pVisor stage | 32 | 5/5 | 160/160 | 0 | 0 | 407.8 |
| pVisor stage | 64 | 5/5 | 320/320 | 0 | 0 | 804.5 |
| pVisor stage | 128 | 5/5 | 640/640 | 0 | 0 | 1600.4 |
| pVisor VM | 32 | 5/5 | 160/160 | 0 | 0 | 2047.9 |
| pVisor VM | 64 | 0/5 | 7/320 | 0 | 0 | — |
| pVisor VM | 128 | 0/5 | 0/640 | 0 | 5 | — |
| Podman | 32 | 5/5 | 160/160 | 0 | 0 | 902.8 |
| Podman | 64 | 5/5 | 320/320 | 0 | 0 | 1806.9 |
| Podman | 128 | 0/5 | 141/640 | 384 | 5 | — |
Stage passes five rounds at idle concurrency 128, but adding private data and Git work reduces its highest wholly successful tested level to 32. Plan the two workloads separately; discrete levels also do not establish an exact maximum.
Compressed parked snapshots versus container pause have not completed validation, and snapshot file size or single-VM reclamation does not establish capacity. Firecracker/QEMU density under this budget and matching macOS capacity are unmeasured; their single-task latency is in the end-to-end tasks.
Sources and reproduction¶
Comparison method · Runner manual
Complete CSV/JSON retains attempts, complete batches, failure reasons, unknowns, OOM, observed ranges and source digests for every condition. It remains with raw records in local cohorts or the documentation data archive; failed batches remain in capacity denominators.
Historical cohorts retain their pinned sources, artifacts and timing scope. See the benchmark registry for active experiments and preparation status.