<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Payload Scaling — Photon Ring</title>
<meta name="description" content="How Photon Ring latency scales with payload size, from 8 bytes to 4 KiB, compared against disruptor-rs.">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⊙</text></svg>">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #0d1117; --bg-surface: #161b22; --bg-raised: #1c2128;
--border: #30363d; --border-dim: #21262d;
--text: #c9d1d9; --text-dim: #8b949e; --text-bright: #f0f6fc;
--accent: #58a6ff; --accent-dim: #1f6feb;
--green: #3fb950; --amber: #e3b341;
--radius: 6px; --radius-lg: 10px;
--mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}
html { scroll-behavior: smooth; }
body { background: var(--bg); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; font-size: 16px; line-height: 1.7; -webkit-font-smoothing: antialiased; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
.container { max-width: 960px; margin: 0 auto; padding: 0 24px; }
nav { position: sticky; top: 0; z-index: 100; background: rgba(13,17,23,0.92); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); }
.nav-inner { display: flex; align-items: center; gap: 8px; height: 56px; max-width: 1100px; margin: 0 auto; padding: 0 24px; }
.nav-brand { font-weight: 700; font-size: 1rem; color: var(--text-bright); text-decoration: none; display: flex; align-items: center; gap: 8px; }
.nav-brand:hover { color: var(--accent); text-decoration: none; }
.nav-links { display: flex; gap: 4px; margin-left: auto; list-style: none; }
.nav-links a { padding: 6px 12px; border-radius: var(--radius); font-size: 0.875rem; color: var(--text-dim); transition: color 0.15s, background 0.15s; white-space: nowrap; }
.nav-links a:hover { color: var(--text-bright); background: var(--bg-raised); text-decoration: none; }
.page-header { padding: 48px 0 36px; border-bottom: 1px solid var(--border-dim); }
.page-header h1 { font-size: 2rem; font-weight: 800; color: var(--text-bright); margin-bottom: 8px; }
.page-header p { color: var(--text-dim); }
.breadcrumb { font-size: 0.85rem; color: var(--text-dim); margin-bottom: 12px; }
.content { padding: 48px 0; }
h2 { font-size: 1.3rem; font-weight: 700; color: var(--text-bright); margin: 40px 0 16px; padding-bottom: 8px; border-bottom: 1px solid var(--border-dim); }
h2:first-child { margin-top: 0; }
h3 { font-size: 1rem; font-weight: 600; color: var(--text-bright); margin: 24px 0 12px; }
p { margin-bottom: 16px; }
.table-wrapper { overflow-x: auto; margin: 20px 0; border-radius: var(--radius-lg); border: 1px solid var(--border); }
table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
thead th { background: var(--bg-raised); color: var(--text-bright); font-weight: 600; padding: 10px 16px; text-align: left; border-bottom: 1px solid var(--border); white-space: nowrap; }
tbody tr:nth-child(even) { background: var(--bg-surface); }
tbody td { padding: 9px 16px; border-bottom: 1px solid var(--border-dim); font-family: var(--mono); font-size: 0.83rem; }
tbody td:first-child { font-family: inherit; font-size: 0.875rem; color: var(--text-bright); font-weight: 600; }
tbody tr:last-child td { border-bottom: none; }
.td-best { color: var(--green); font-weight: 600; }
.callout { background: var(--bg-surface); border-left: 3px solid var(--accent); border-radius: 0 var(--radius) var(--radius) 0; padding: 14px 18px; font-size: 0.9rem; color: var(--text-dim); margin: 20px 0; }
.callout-warn { border-left-color: var(--amber); }
.callout strong { color: var(--text-bright); }
code { font-family: var(--mono); font-size: 0.875em; background: var(--bg-raised); padding: 2px 6px; border-radius: 4px; color: var(--accent); }
.chart-card { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 28px; margin: 28px 0; }
.chart-title { font-size: 0.9rem; font-weight: 600; color: var(--text-bright); margin-bottom: 4px; }
.chart-sub { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 20px; }
.chart-container { position: relative; height: 320px; }
.payload-img { width: 100%; border-radius: var(--radius-lg); border: 1px solid var(--border); display: block; margin: 24px 0; }
.code-block { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow-x: auto; margin: 16px 0; }
.code-block pre { padding: 20px 24px; font-family: var(--mono); font-size: 0.875rem; line-height: 1.65; color: var(--text); }
footer { background: var(--bg-surface); border-top: 1px solid var(--border); padding: 32px 0; text-align: center; color: var(--text-dim); font-size: 0.875rem; }
footer a { color: var(--text-dim); }
footer a:hover { color: var(--accent); }
</style>
</head>
<body>
<nav>
<div class="nav-inner">
<a class="nav-brand" href="index.html">
<span>⊙</span> Photon Ring
</a>
<ul class="nav-links">
<li><a href="index.html#overview">Overview</a></li>
<li><a href="index.html#benchmarks">Benchmarks</a></li>
<li><a href="index.html#comparison">Comparison</a></li>
<li><a href="index.html#api">API</a></li>
<li><a href="index.html#get-started">Get Started</a></li>
<li><a href="https://docs.rs/photon-ring" target="_blank" rel="noopener">docs.rs ↗</a></li>
<li><a href="https://github.com/userFRM/photon-ring" target="_blank" rel="noopener">GitHub ↗</a></li>
</ul>
</div>
</nav>
<div class="page-header">
<div class="container">
<div class="breadcrumb"><a href="index.html">Photon Ring</a> / Payload Scaling</div>
<h1>Payload Scaling Analysis</h1>
<p>How Photon Ring latency scales with payload size from 8 bytes to 4 KiB, with disruptor-rs comparison.</p>
</div>
</div>
<div class="content">
<div class="container">
<img class="payload-img" src="images/payload-scaling.png" alt="Payload scaling chart: Photon Ring vs disruptor-rs across 8B-4KiB payloads">
<h2>Environment</h2>
<div class="table-wrapper">
<table>
<thead><tr><th>Machine</th><th>CPU</th><th>OS</th><th>Rust</th></tr></thead>
<tbody>
<tr><td>A (primary)</td><td>Intel Core i7-10700KF @ 3.80 GHz</td><td>Linux 6.8</td><td>1.93.1</td></tr>
<tr><td>B (secondary)</td><td>Apple M1 Pro</td><td>macOS 26.3</td><td>1.92.0</td></tr>
</tbody>
</table>
</div>
<p>Framework: Criterion, 100 samples, 3-second warmup, ring size 4096 slots.</p>
<h2>Same-Thread Roundtrip</h2>
<p>L1-hot, measures pure instruction cost with no cache-coherence traffic.</p>
<div class="table-wrapper">
<table>
<thead>
<tr><th>Payload</th><th>Latency (A)</th><th>Latency (B)</th><th>Cache lines</th><th>Notes</th></tr>
</thead>
<tbody>
<tr><td>8 B</td><td class="td-best">2.4 ns</td><td>8.6 ns</td><td>1</td><td>Stamp + value share one 64B line</td></tr>
<tr><td>16 B</td><td>9.8 ns</td><td>11.3 ns</td><td>1</td><td></td></tr>
<tr><td>32 B</td><td>11.8 ns</td><td>13.0 ns</td><td>1</td><td></td></tr>
<tr><td>64 B</td><td>18.8 ns</td><td>16.4 ns</td><td>2</td><td>Slot = 72B, spills to 2 lines</td></tr>
<tr><td>128 B</td><td>23.3 ns</td><td>25.4 ns</td><td>3</td><td></td></tr>
<tr><td>256 B</td><td>34.4 ns</td><td>41.2 ns</td><td>5</td><td></td></tr>
<tr><td>512 B</td><td>55.9 ns</td><td>69.6 ns</td><td>9</td><td></td></tr>
<tr><td>1 KB</td><td>88.1 ns</td><td>127.9 ns</td><td>17</td><td>memcpy starts to dominate</td></tr>
<tr><td>2 KB</td><td>149.6 ns</td><td>244.6 ns</td><td>33</td><td></td></tr>
<tr><td>4 KB</td><td>361.6 ns</td><td>500.9 ns</td><td>65</td><td>~5.6 ns per cache line</td></tr>
</tbody>
</table>
</div>
<h2>Cross-Thread Roundtrip vs disruptor-rs</h2>
<div class="callout callout-warn">
<strong>Methodology note:</strong> The 117 ns at 8B here vs 95 ns in the main benchmarks reflects
differences in Criterion warm-up, iterator structure, and type-generic overhead. The disruptor-rs
column is modeled (not measured at each payload size) using the baseline 133 ns from the actual
<code>disruptor</code> crate benchmark plus estimated per-cache-line transfer costs.
</div>
<div class="table-wrapper">
<table>
<thead>
<tr><th>Payload</th><th>Photon Ring (A)</th><th>Photon Ring (B)</th><th>Disruptor (modeled, A)</th><th>Advantage (A)</th></tr>
</thead>
<tbody>
<tr><td>8 B</td><td class="td-best">117 ns</td><td>156.7 ns</td><td>133 ns</td><td>12% faster</td></tr>
<tr><td>64 B</td><td class="td-best">125 ns</td><td>195.8 ns</td><td>145 ns</td><td>14% faster</td></tr>
<tr><td>256 B</td><td class="td-best">148 ns</td><td>156.7 ns</td><td>181 ns</td><td>18% faster</td></tr>
<tr><td>512 B</td><td class="td-best">163 ns</td><td>167.6 ns</td><td>229 ns</td><td>29% faster</td></tr>
<tr><td>1 KB</td><td class="td-best">191 ns</td><td>226.5 ns</td><td>325 ns</td><td>41% faster</td></tr>
<tr><td>4 KB</td><td class="td-best">342 ns</td><td>369.7 ns</td><td>901 ns</td><td>62% faster</td></tr>
</tbody>
</table>
</div>
<div class="chart-card">
<div class="chart-title">Cross-Thread Latency vs Payload Size (Intel i7-10700KF)</div>
<div class="chart-sub">Photon Ring vs modeled disruptor-rs baseline. Log x-axis.</div>
<div class="chart-container">
<canvas id="payloadChart"></canvas>
</div>
</div>
<h2>Key Observations</h2>
<h3>The memcpy is cheap relative to cache coherence</h3>
<p>
For payloads up to 56 bytes (one cache line with the stamp), the memcpy costs roughly 2–3 ns
against a ~96 ns cache-coherence transfer. The copy is <strong style="color:var(--text-bright);">roughly 3% of total latency</strong>.
</p>
<h3>Photon Ring outperforms at all tested payload sizes</h3>
<p>The performance advantage grows with payload size because:</p>
<ol style="margin-left:24px;margin-bottom:16px;">
<li style="margin-bottom:8px;"><strong style="color:var(--text-bright);">The Disruptor pays the same cache coherence cost.</strong> Consumers must still transfer the same cache lines from the publisher, whether they read in-place or copy.</li>
<li style="margin-bottom:8px;"><strong style="color:var(--text-bright);">The Disruptor has higher base overhead.</strong> Sequence barrier load + event handler dispatch + shared cursor contention adds ~37 ns over Photon Ring's stamp-only fast path.</li>
<li style="margin-bottom:8px;"><strong style="color:var(--text-bright);">x86 memcpy is extremely efficient.</strong> <code>rep movsb</code> with ERMS (Enhanced REP MOVSB) achieves near-memory-bandwidth speeds. The 4 KB copy costs ~200 ns, but the Disruptor's multi-line coherence transfer costs more.</li>
</ol>
<h2>Regenerating</h2>
<div class="code-block">
<pre>cargo bench --bench payload_scaling
python3 scripts/plot_payload_scaling.py</pre>
</div>
</div>
</div>
<footer>
<div class="container">
Licensed under <a href="https://github.com/userFRM/photon-ring/blob/master/LICENSE-APACHE" target="_blank" rel="noopener">Apache-2.0</a>.
© 2026 Photon Ring Contributors.
— <a href="index.html">Back to home</a>
</div>
</footer>
<script>
(function () {
Chart.defaults.color = '#8b949e';
Chart.defaults.borderColor = '#30363d';
Chart.defaults.font.family = "SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace";
Chart.defaults.font.size = 11;
const payloads = ['8 B', '64 B', '256 B', '512 B', '1 KB', '4 KB'];
const photon = [117, 125, 148, 163, 191, 342];
const disrupt = [133, 145, 181, 229, 325, 901];
new Chart(document.getElementById('payloadChart'), {
type: 'line',
data: {
labels: payloads,
datasets: [
{
label: 'Photon Ring (Intel i7-10700KF)',
data: photon,
borderColor: 'rgba(88,166,255,0.9)',
backgroundColor: 'rgba(88,166,255,0.12)',
fill: true,
tension: 0.3,
pointRadius: 5,
pointBackgroundColor: 'rgba(88,166,255,0.9)',
borderWidth: 2,
},
{
label: 'disruptor-rs (modeled, Intel i7-10700KF)',
data: disrupt,
borderColor: 'rgba(227,179,65,0.85)',
backgroundColor: 'rgba(227,179,65,0.08)',
fill: true,
tension: 0.3,
pointRadius: 5,
pointBackgroundColor: 'rgba(227,179,65,0.85)',
borderWidth: 2,
borderDash: [5, 3],
},
],
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'bottom', labels: { boxWidth: 12, padding: 16 } },
tooltip: {
callbacks: {
label: (ctx) => ` ${ctx.dataset.label}: ${ctx.raw} ns`,
},
},
},
scales: {
y: {
title: { display: true, text: 'Roundtrip latency (ns)', color: '#8b949e' },
grid: { color: 'rgba(48,54,61,0.6)' },
beginAtZero: true,
},
x: {
title: { display: true, text: 'Payload size', color: '#8b949e' },
grid: { color: 'rgba(48,54,61,0.6)' },
},
},
},
});
}());
</script>
</body>
</html>