mirror of
https://github.com/hanzoai/papers.git
synced 2026-11-02 13:32:30 +00:00
Every measured constant in hanzo-dormant-agents came from bench lanes that have since been re-run, and two of them from a lane that was deleted. The paper is the last consumer to be corrected and the one where it matters most. The pooled row was the problem. Section 6 reported 37.54 ms for "a command dispatched into a container that is already up" and built a paragraph on it — "pooling collapses most of the gap, and is the only tier that matters at fleet scale" — which the conclusion then turned into policy: pool the expensive boundary so a fleet pays the pooled number in steady state. That row was docker exec, on a runtime this system does not use. The runtime it does use has no exec, no attach and no pool. Every call boots. So the table is hanzo-vm now: 309 ms cold, 335 p95, and 311 ms from a checkpoint — which is the same number, because a checkpoint carries the filesystem an earlier run left and the kernel boots either way. The pooling paragraph is replaced by what is true: there is no warm tier, the published resume figures elsewhere are memory snapshots and ours is not, and setting the two side by side would claim a mechanism by borrowing its name. The cost of not having it is stated instead — about 3x on a whole agent call. Section 6 also said our figure "compares favourably to the published cold-start figures". At 309 ms it does not: it is slower than the under-200 ms published for Firecracker sandboxes, faster than the container platforms, and all of those were taken by their authors on their own hardware. The paper says that now, including that quoting their hardware back at them is not a defence. The rest are re-measurements: a goroutine spawns in 125 ns (the 187 was a fresh binary's first run, which is 1.65x its own steady state), a million wake in 107 ms, a V8 context is 0.13 ms, an isolate 0.35 ms, wazero 7.8 us, goja 2.4 us, gpython 25.0 us. The isolation ratio is 2377x, not 1016x. Rebuilt: 12 pages, no stale figure survives in the PDF. Co-authored-by: Hanzo Dev <[email protected]>
119 lines
4.8 KiB
TeX
119 lines
4.8 KiB
TeX
\section{Related work}
|
|
\label{sec:related}
|
|
|
|
Hosted sandbox platforms publish cold-start and minimum-memory figures for the
|
|
container tier: E2B under 200\,ms with a 512\,MB minimum~\cite{e2b}, Modal
|
|
around a second with a 128\,MB minimum~\cite{modal}, and Cloudflare Workers
|
|
1--3\,s for a container with 256\,MB~\cite{cfworkers}. These are the numbers that
|
|
set the industry estimate this paper takes apart, and \S\ref{sec:isolation}
|
|
measures the same primitive rather than a cheaper one in order to compare
|
|
honestly.
|
|
|
|
The in-process tier has a long lineage that agent platforms have mostly not
|
|
drawn on. V8 isolates as a multi-tenant unit are the basis of edge function
|
|
platforms~\cite{cfworkers}; WebAssembly's capability model gives a deny-by-default
|
|
boundary at a fraction of a container's cost~\cite{wasm}; and pure-Go
|
|
implementations of all three runtimes measured here~\cite{wazero,goja,gpython}
|
|
make the tier available without CGO or a second process. The contribution of
|
|
\S\ref{sec:code} is not the runtimes but the measurement that all three sit in
|
|
the microseconds, which is what makes the three-rung ladder in
|
|
\S\ref{sec:isolation} a practical policy rather than a taxonomy.
|
|
|
|
The residency argument is the agent-scale case of the tenant-scale one made
|
|
in~\cite{unifiedtenant}, where a per-tenant SQLite file was measured at
|
|
${\approx}0.25$\,MB resident and the conclusion was that memory scales with
|
|
concurrency rather than registrations. Green threads as a cheap concurrency unit
|
|
predate all of this and the goroutine implementation's growable
|
|
stacks~\cite{gostack} are what make the \rGoPer{}-byte figure possible.
|
|
|
|
\section{Conclusion}
|
|
\label{sec:conclusion}
|
|
|
|
An agent is not a process, and costing it as one inflates the estimate by
|
|
roughly five orders of magnitude. Measured separately on one laptop: state at
|
|
rest is \rFleetPer{}\,bytes, execution at rest is \rGoPer{}\,bytes, and isolation
|
|
is \rVeight{}--\rVm{}\,ms depending on which boundary the workload actually
|
|
needs.
|
|
|
|
The practical consequence is a policy rather than a product. Take the cheapest
|
|
rung the threat model permits; keep dormant agents as rows and rehydrate them in
|
|
\rFleetResume{}\,ms rather than holding loops open; and size memory against what
|
|
the agents \emph{hold}, since the primitives holding them contribute nothing
|
|
measurable. The one rung we do not yet offer is a warm tier for the expensive
|
|
boundary: every call pays \rVm{}\,ms, a checkpoint saves the disk rather than the
|
|
boot, and closing that gap is worth about $3\times$ on a whole agent call.
|
|
|
|
The result we would most like to see contested is the one we flagged hardest:
|
|
\rGoPer{}\,bytes is the residency of an agent that holds nothing, and a fleet of
|
|
agents that hold something will be dominated by that something. The measurement
|
|
says the platform overhead is not the problem. It does not say there is no
|
|
problem.
|
|
|
|
\section*{Reproducing}
|
|
|
|
The scripts are in \texttt{hanzoai/cloud} under \texttt{bench/}, one directory
|
|
per measurement, and each prints the table it produced:
|
|
|
|
\begin{lstlisting}[language=bash]
|
|
node fleet/fleet.mjs /tmp/fleet # state at rest
|
|
go build -o /tmp/goro . && /tmp/goro # execution at rest, and the runtimes
|
|
node sandbox/sandbox.mjs # isolation (needs a container runtime)
|
|
node pricing/pricing.mjs # rates
|
|
\end{lstlisting}
|
|
|
|
\begin{thebibliography}{9}
|
|
|
|
\bibitem{unifiedtenant}
|
|
Hanzo AI Research.
|
|
\newblock The Unified Sovereign-Tenant Cloud: Linear Shared-Nothing Scaling via
|
|
Per-Tenant SQLite and In-Process Composition.
|
|
\newblock Hanzo AI Research, 2026.
|
|
|
|
\bibitem{gostack}
|
|
The Go Authors.
|
|
\newblock Goroutines and the runtime scheduler: growable stacks.
|
|
\newblock \texttt{https://go.dev/doc/}, Go 1.27 runtime documentation.
|
|
|
|
\bibitem{wazero}
|
|
Tetrate.
|
|
\newblock wazero: the zero-dependency WebAssembly runtime for Go.
|
|
\newblock \texttt{https://wazero.io}.
|
|
|
|
\bibitem{goja}
|
|
D.~Siegel et al.
|
|
\newblock goja: ECMAScript/JavaScript engine in pure Go.
|
|
\newblock \texttt{https://github.com/dop251/goja}.
|
|
|
|
\bibitem{gpython}
|
|
N.~Craig-Wood.
|
|
\newblock gpython: a Python interpreter written in Go.
|
|
\newblock \texttt{https://github.com/go-python/gpython}.
|
|
|
|
\bibitem{wasm}
|
|
A.~Haas, A.~Rossberg, D.~L.~Schuff, B.~L.~Titzer, M.~Holman, D.~Gohman,
|
|
L.~Wagner, A.~Zakai, and J.~F.~Bastien.
|
|
\newblock Bringing the Web up to Speed with WebAssembly.
|
|
\newblock In \emph{PLDI}, 2017.
|
|
|
|
\bibitem{e2b}
|
|
E2B.
|
|
\newblock Sandbox documentation: startup time and resource limits.
|
|
\newblock \texttt{https://e2b.dev/docs}.
|
|
|
|
\bibitem{modal}
|
|
Modal.
|
|
\newblock Documentation: cold start and container resource minimums.
|
|
\newblock \texttt{https://modal.com/docs}.
|
|
|
|
\bibitem{cfworkers}
|
|
Cloudflare.
|
|
\newblock Workers and Containers: isolates, startup latency and instance types.
|
|
\newblock \texttt{https://developers.cloudflare.com/workers/}.
|
|
|
|
\bibitem{railway}
|
|
Railway.
|
|
\newblock Pricing: vCPU and memory rates.
|
|
\newblock \texttt{https://railway.com/pricing}.
|
|
|
|
\end{thebibliography}
|