boxer

Benchmarks

What boxer costs against other sandboxes and across its own backends, with the date and conditions of each measurement.

The latest measurements are from 2026-09-28. A no-op command in a running smolvm sandbox takes 33 ms through boxer run, against 29 ms for docker exec and 232 ms for a fresh docker run.

Every number on this page comes from one Apple M4 Mac (10 cores, 24 GB, macOS 26.5.2). The scripts are in bench/. Each script writes its raw results beside it, and bench/README.md has the full method. A number measured once is labelled a single sample.

measurementscriptrecordedboxer build
A command in a running sandboxmake bench2026-09-28v1.0.0-55-g34ca729, smolvm 1.16.1
Across boxer's backendsbench/backends.sh2026-09-28 (podman 2026-09-25)v1.0.0-55-g34ca729
[urls] on and offbench/urls.sh2026-09-28v1.0.0-55-g34ca729
Starting a development stackmake bench-devserver2026-09-25not recorded
Several sandboxes at oncebench/parallel-clean.sh2026-09-25not recorded

"Recorded" is the date the results were committed to bench/.

The two 2026-09-25 rows were not re-measured after the 2026-09-27 fixes, which changed how the container backends publish ports, gave every smolvm machine an idle workload, and made boxer up with [urls] on wait for the proxy and the route.

A command in a running sandbox

make bench runs a no-op and a set of ordinary workloads in an already-running sandbox. It takes 20 samples per cell and reports the median. Docker was 29.4.0.

no-op
seatbelt (the sandbox Claude Code and Codex use on macOS)~8 ms
boxer run, smolvm33 ms
docker exec into a running container29 ms
docker run, a fresh container per command232 ms
  • boxer is within 4 ms of docker exec on every workload that is not I/O-bound.
  • boxer is about 7x faster than a container per command, because the sandbox per worktree stays warm.
  • Seatbelt is faster. It filters syscalls around a host process and does not start another kernel.
  • The worktree mount adds cost. A recursive grep takes 2.4x as long as in a warm container, and so does writing 200 files. The cost comes from virtiofs.
  • boxer adds 19 to 27 ms over raw smolvm machine exec, most of it starting the smolvm process.
  • The rewrite hook that every intercepted command passes through takes 4 ms.

Starting a development stack

make bench-devserver times how long a Next.js dev server takes to answer HTTP 200. Every contender gets node:24-alpine, 10 vCPU and 8 GB, an empty npm cache, the same lockfile and a cleared .next.

start a session (deps installed)install dependencies
no sandbox6.8 s3.5 s
boxer, smolvm7.6 s9.2 s
OrbStack (a container)10.8 s5.2 s

You pay the session start every time. boxer adds 0.8 s over no sandbox. Installing dependencies is slower in boxer because the guest writes through the mount. [prep] and the host package-cache mounts move that work out of the guest.

Several sandboxes at once

bench/parallel-clean.sh runs at Vercel Sandbox's default shape, 2 vCPU and 4 GB each, with one linked worktree per sandbox. Every cell starts from a wiped host.

sandboxesboxer, readyOrbStack, ready
17.6 s10.2 s
322.3 s18.8 s
526.3 s27.1 s

Past the first sandbox, Next.js compiling on ten shared cores takes most of the time. One and three are single samples. Five is the median of three to four.

Across boxer's backends

bench/backends.sh runs one backend at a time, alone on the host, three samples each, with a Next.js dev server per worktree at 2 vCPU and 4 GB. There is no Linux run of this benchmark.

These figures are not comparable with the table above. bench/parallel-clean.sh restarts OrbStack and prunes its image cache before every cell and times plain docker run, so its container rows include a cold runtime VM. bench/backends.sh empties every backend but does not restart it, and times each one through boxer.

backendboundaryone worktreethree worktrees
dockershared kernel4.3 s10.9 s
Apple containerkernel per sandbox5.3 s14.4 s
smolvmkernel per sandbox6.4 s15.6 s

A kernel per sandbox costs about 1 to 2 s on the first worktree, and 3.5 to 4.7 s at three. docker was the steadiest, with all three one-worktree samples at 4.3 s. Apple container had one slow sample out of three (8.3 s against 5.3 s), as it did on 2026-09-25.

Podman was not rerun because the host had no podman machine. On 2026-09-25 it took 3.6 s for one worktree and 25.9 s for three. Every other backend was 40 to 50% slower at three worktrees on that day than on 2026-09-28, docker included, with the same app and script. The cause was host state, which was not recorded. Compare rows within one run, not across the two. bench/backends-2026-09-25.jsonl has that run.

[urls] on and off

bench/urls.sh brings up two worktrees that differ only in [urls] enabled, then times five interleaved pairs of each call. The table shows medians.

boxer up on a running sandboxwarm boxer run
[urls] off14.2 ms30.7 ms
[urls] on14.4 ms32.0 ms

The difference is within the spread of the samples. The route is registered when the sandbox starts, so a later boxer up finds it in place.

Memory

A sandbox serving a Next.js dev server touches about 1.2 GB inside the guest, 642 MB of it node's own heap, and does not grow to fill a larger allocation. That figure replicates across runs.

The whole-host measurement varied up to 2.1x within one configuration, and halving each guest's memory produced both the lowest and the highest figure. A microVM per worktree costs a kernel, a guest userland and a page cache more than a shared kernel. How much more on this workload is unmeasured.

Withdrawn

Repeated runs showed these three earlier claims were wrong:

  • "About 243 MB per sandbox, crossover at six." This was measured on sandboxes running nothing. One serving a dev server costs about a gigabyte, most of it node.
  • "Four times OrbStack's memory at five sandboxes." The harness ran every cell in one process, so the container runtime's VM had already grown and was charged only for marginal growth. From a wiped host the same cell read 2.2 to 2.9 GB, not 501 MB.
  • "Halving the guest allocation saves memory." It produced the widest spread measured.

Each came from a single sample.

Caveats

  • One host, one architecture. On a Mac, docker exec crosses a VM boundary too. On a Linux host every container row would be cheaper and the comparison would change.
  • Cache state dominates cold start. A first run pulls the image. Every figure above is warm unless it says otherwise.
  • Benchmarks do not fail CI. The evaluation tiers check whether boxer works.

On this page