mirror of
https://github.com/hanzoai/papers.git
synced 2026-11-03 02:27:30 +00:00
Every author block and the authorship standard said Los Angeles; Hanzo has been in San Francisco since at least 2016. The five catalogue PDFs whose sources changed are rebuilt so papers.hanzo.ai says so too. Co-authored-by: Hanzo Dev <[email protected]>
109 lines
5.0 KiB
TeX
109 lines
5.0 KiB
TeX
% What a Dormant Agent Costs
|
|
\documentclass[11pt]{article}
|
|
\usepackage{../shared/hanzocover}
|
|
\usepackage{amsmath, amssymb}
|
|
\usepackage{booktabs}
|
|
\usepackage{graphicx}
|
|
\usepackage{xcolor}
|
|
\usepackage{enumitem}
|
|
\usepackage{array}
|
|
\usepackage{listings}
|
|
\input{../shared/lstlang}
|
|
\usepackage{hyperref}
|
|
\hypersetup{colorlinks=true,linkcolor=black,citecolor=blue,urlcolor=blue}
|
|
|
|
% Provenance, on every number. A reader should never have to guess whether a
|
|
% figure came off a machine or out of a spreadsheet.
|
|
\newcommand{\meas}{\textcolor{blue!60!black}{\small[measured]}}
|
|
\newcommand{\modeled}{\textcolor{orange!70!black}{\small[modeled]}}
|
|
\newcommand{\cited}{\textcolor{purple!70!black}{\small[cited]}}
|
|
|
|
% Every measured constant is a macro, and results-data.tex overrides all of
|
|
% them from the runs. The defaults below are placeholders: if the generated
|
|
% file is ever missing, the paper prints XXX rather than a stale number that
|
|
% reads as real.
|
|
\newcommand{\ph}{\textbf{XXX}}
|
|
\newcommand{\rFleetAgents}{\ph} \newcommand{\rFleetRecord}{\ph}
|
|
\newcommand{\rFleetDisk}{\ph} \newcommand{\rFleetPer}{\ph}
|
|
\newcommand{\rFleetWriteS}{\ph} \newcommand{\rFleetRate}{\ph}
|
|
\newcommand{\rFleetResume}{\ph} \newcommand{\rFleetResumeCold}{\ph}
|
|
\newcommand{\rGoSpawn}{\ph} \newcommand{\rGoSpawnLo}{\ph}
|
|
\newcommand{\rGoSpawnHi}{\ph} \newcommand{\rGoPer}{\ph}
|
|
\newcommand{\rGoHeap}{\ph} \newcommand{\rGoWake}{\ph}
|
|
\newcommand{\rGoWakeLo}{\ph} \newcommand{\rGoWakeHi}{\ph}
|
|
\newcommand{\rWazero}{\ph} \newcommand{\rWazeroHi}{\ph}
|
|
\newcommand{\rWazeroCall}{\ph} \newcommand{\rGoja}{\ph}
|
|
\newcommand{\rGojaLo}{\ph} \newcommand{\rGojaHi}{\ph}
|
|
\newcommand{\rGojaWarm}{\ph} \newcommand{\rGojaWarmLo}{\ph}
|
|
\newcommand{\rGojaWarmHi}{\ph} \newcommand{\rGpython}{\ph}
|
|
\newcommand{\rGpythonLo}{\ph} \newcommand{\rGpythonHi}{\ph}
|
|
\newcommand{\rVeight}{\ph} \newcommand{\rVeightP}{\ph}
|
|
\newcommand{\rVm}{\ph} \newcommand{\rVmP}{\ph}
|
|
\newcommand{\rVmCkpt}{\ph} \newcommand{\rVmCkptP}{\ph}
|
|
\newcommand{\rVmRatio}{\ph} \newcommand{\rPlaneCost}{\ph}
|
|
\newcommand{\rPlaneCpu}{\ph} \newcommand{\rPlaneRam}{\ph}
|
|
\newcommand{\rFleetStorage}{\ph}
|
|
\input{results-data}
|
|
|
|
\title{What a Dormant Agent Costs\\[0.3em]
|
|
{\large State, Execution and Isolation Measured Separately\\
|
|
at a Fleet of One Million}}
|
|
\author{
|
|
Hanzo AI Research\thanks{Corresponding author: [email protected]} \\
|
|
\textit{Hanzo Industries Inc (Techstars '17)} \\
|
|
San Francisco, California \\
|
|
\texttt{https://hanzo.ai}
|
|
}
|
|
\date{Measurement pass: 2026-09-07 (Apple M-series, darwin/arm64, 16 cores, Go 1.27.1)}
|
|
|
|
\begin{document}
|
|
|
|
\hanzocoverpage
|
|
\maketitle
|
|
|
|
\begin{abstract}
|
|
An agent platform is usually costed as though an agent were a process. It is the
|
|
natural reading of the deployment shape --- one container per agent --- and it
|
|
sets the per-agent floor at the container runtime's minimum reservation, which
|
|
on commodity platforms is 128--512\,MB\@. At that floor a fleet of a million
|
|
agents is a datacenter, and every design decision downstream of the estimate is
|
|
made in its shadow.
|
|
|
|
We take the estimate apart. An idle agent is three separable things: the
|
|
\emph{state} it will resume from, the \emph{execution context} that holds its
|
|
loop, and the \emph{isolation boundary} its code runs behind. These have no
|
|
reason to cost the same, and measured on one laptop they differ by five orders
|
|
of magnitude. State at rest is a row: \textbf{\rFleetPer{}\,bytes} on disk
|
|
\meas{}, so \rFleetAgents{} dormant agents occupy \textbf{\rFleetDisk{}\,MiB}
|
|
--- written at \rFleetRate{}\,agents/s and resumed in
|
|
\textbf{\rFleetResume{}\,ms} in-process. Execution at rest is a goroutine:
|
|
\textbf{\rGoPer{}\,bytes} of heap \meas{}, identical on every run, so a million
|
|
live loops are \rGoHeap{}\,MB and each starts in \rGoSpawn{}\,ns. Isolation is
|
|
the expensive one, and it is expensive for a reason: an in-process V8 context
|
|
costs \rVeight{}\,ms \meas{} but runs only JavaScript, while a microVM
|
|
costs \rVm{}\,ms --- \rVmRatio{}$\times$ more --- and is the only one of the
|
|
two that can run a test suite, a package manager or a shell.
|
|
|
|
The conclusion is not that containers are wasteful. It is that a fleet pays for
|
|
isolation \emph{per running agent}, not per registered one, while the industry
|
|
estimate charges the isolation price to every agent in the fleet whether or not
|
|
it is doing anything. Separating the three costs makes the dormant majority
|
|
nearly free: \rFleetAgents{} dormant agents are \rFleetStorage{} dollars a month
|
|
of storage \modeled{} beside a control plane that costs \$\rPlaneCost{}
|
|
\cited{}. We give the capacity model this implies, and we are explicit in
|
|
\S\ref{sec:limits} about what \rGoPer{}\,bytes is: a floor for an agent holding
|
|
nothing, not a forecast for an agent holding a conversation.
|
|
\end{abstract}
|
|
|
|
\input{sections/01-introduction}
|
|
\input{sections/02-method}
|
|
\input{sections/03-state}
|
|
\input{sections/04-execution}
|
|
\input{sections/05-code}
|
|
\input{sections/06-isolation}
|
|
\input{sections/07-capacity}
|
|
\input{sections/08-limits}
|
|
\input{sections/99-conclusion}
|
|
|
|
\end{document}
|