Files
papers/lux-zap-benchmarks/sections/07-concurrent-connection-scalability.tex
zeekay abf99d05fc papers: reorganize into per-paper dirs, add Antje Worring as co-author
Restructured from flat .tex/.pdf files into per-paper subdirectories.
Added Antje Worring as co-author on all papers.
Synced PDFs to pdfs/ for download site.
2026-04-18 21:50:07 -07:00

64 lines
3.1 KiB
TeX

\section{Concurrent Connection Scalability}
%% ============================================================================
\subsection{Throughput vs.\ Connection Count}
\begin{table}[h]
\centering
\caption{Aggregate throughput (messages/sec) by concurrent connection count}
\label{tab:conns}
\begin{tabular}{lrrrrr}
\toprule
\textbf{Protocol} & \textbf{100} & \textbf{1,000} & \textbf{10,000} & \textbf{100,000} & \textbf{Scaling} \\
\midrule
\rowcolor{luxblue!10}
ZAP & 4,180K & 4,120K & 3,940K & 3,610K & 0.86$\times$ \\
FlatBuffers & 3,810K & 3,690K & 3,280K & 2,740K & 0.72$\times$ \\
Cap'n Proto & 3,120K & 2,940K & 2,510K & 1,920K & 0.62$\times$ \\
gRPC & 2,450K & 2,180K & 1,420K & 680K & 0.28$\times$ \\
QUIC & 2,100K & 1,980K & 1,610K & 1,180K & 0.56$\times$ \\
Protobuf-mux & 1,280K & 1,040K & 620K & 310K & 0.24$\times$ \\
JSON-RPC & 890K & 640K & 280K & 92K & 0.10$\times$ \\
\bottomrule
\end{tabular}
\end{table}
The ``Scaling'' column shows the ratio of throughput at 100K connections to throughput at 100 connections. ZAP retains 86\% of its throughput at 100K connections, compared to 28\% for gRPC and 10\% for JSON-RPC.
\begin{theorem}[Scalability Factor]
The throughput degradation $D(c)$ at $c$ connections is:
\[
D(c) = \frac{T(c)}{T(c_0)} = \frac{1}{1 + \alpha \cdot c \cdot a_{\text{msg}} / H}
\]
where $\alpha$ is the GC overhead coefficient ($\sim$0.3 for Go), $a_{\text{msg}}$ is bytes allocated per message, and $H$ is the heap target. For ZAP with $a_{\text{msg}} = 0$: $D(c) = 1/(1 + 0) = 1$ (linear scaling, bounded only by kernel socket overhead). For gRPC with $a_{\text{msg}} = 576$: $D(100000) = 1/(1 + 0.3 \cdot 100000 \cdot 576 / 4\text{MB}) = 0.19$, consistent with the measured 0.28 (kernel overhead accounts for the difference).
\end{theorem}
\subsection{Per-Connection Overhead}
\begin{table}[h]
\centering
\caption{Memory overhead per connection (steady-state)}
\label{tab:connmem}
\begin{tabular}{lrrr}
\toprule
\textbf{Protocol} & \textbf{KB/conn} & \textbf{100K total} & \textbf{Primary cost} \\
\midrule
\rowcolor{luxblue!10}
ZAP & 8.2 & 800 MB & 8 KB arena buffer \\
FlatBuffers & 12.4 & 1.21 GB & Buffer + vtable cache \\
Cap'n Proto & 14.8 & 1.45 GB & Segment allocator \\
QUIC & 28.3 & 2.77 GB & TLS state + streams \\
gRPC & 64.2 & 6.28 GB & HTTP/2 state + buffers \\
Protobuf-mux & 89.7 & 8.78 GB & Muxer + pubsub + routing \\
JSON-RPC & 16.1 & 1.58 GB & Read/write buffers \\
\bottomrule
\end{tabular}
\end{table}
ZAP's 8.2 KB per connection consists of a single 8 KB pre-allocated arena buffer (the \texttt{buf[8192]} from the protocol specification \cite{zapwire}). gRPC requires 64.2 KB per connection due to HTTP/2 flow control windows, HPACK header tables, and per-stream buffers. Protobuf-mux's 89.7 KB includes protocol multiplexer state, pubsub topic subscriptions, and peer routing tables.
At 100K connections, ZAP uses 800 MB vs.\ gRPC's 6.28 GB---a 7.9$\times$ reduction that determines whether a node can maintain full mesh connectivity on commodity hardware (16 GB RAM).
%% ============================================================================