.nornir/assets/arrowipc_seal_flow.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 560" font-family="'DejaVu Sans', 'Segoe UI', sans-serif">
<defs>
<linearGradient id="board" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0b1c2e"/>
<stop offset="1" stop-color="#06111d"/>
</linearGradient>
<linearGradient id="chip" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#14384f"/>
<stop offset="1" stop-color="#0e2a3e"/>
</linearGradient>
<linearGradient id="hot" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#5a1e1e"/>
<stop offset="1" stop-color="#3a1212"/>
</linearGradient>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto">
<path d="M0,0 L8,3 L0,6 Z" fill="#9fc9e0"/>
</marker>
</defs>
<rect x="0" y="0" width="1180" height="560" fill="url(#board)"/>
<line x1="0" y1="64" x2="1180" y2="64" stroke="#143a52" stroke-width="1"/>
<line x1="0" y1="520" x2="1180" y2="520" stroke="#143a52" stroke-width="1"/>
<text x="40" y="40" fill="#eaf6ff" font-size="22" font-weight="700">znippy arrow-ipc write path</text>
<text x="360" y="40" fill="#9fc9e0" font-size="15">a no-barrier <tspan fill="#bfe6ff" font-weight="700">1→N→1</tspan> blob pipeline (fast) → a <tspan fill="#ff9a9a" font-weight="700">single-threaded seal tail</tspan> (the bottleneck this baseline measures)</text>
<!-- 1: reader -->
<rect x="40" y="170" width="150" height="120" rx="10" fill="url(#chip)" stroke="#2b6f96"/>
<text x="115" y="220" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">reader</text>
<text x="115" y="244" fill="#9fc9e0" font-size="12" text-anchor="middle">Arc<[u8]> slots</text>
<text x="115" y="262" fill="#9fc9e0" font-size="12" text-anchor="middle">zero-copy (Law 1)</text>
<text x="115" y="158" fill="#7fb0cc" font-size="12" text-anchor="middle">1</text>
<!-- N: barrels -->
<g>
<rect x="270" y="120" width="190" height="64" rx="8" fill="url(#chip)" stroke="#2b6f96"/>
<rect x="270" y="198" width="190" height="64" rx="8" fill="url(#chip)" stroke="#2b6f96"/>
<rect x="270" y="276" width="190" height="64" rx="8" fill="url(#chip)" stroke="#2b6f96"/>
<text x="365" y="158" fill="#eaf6ff" font-size="14" text-anchor="middle">blake3 + zstd</text>
<text x="365" y="236" fill="#eaf6ff" font-size="14" text-anchor="middle">blake3 + zstd</text>
<text x="365" y="314" fill="#eaf6ff" font-size="14" text-anchor="middle">blake3 + zstd</text>
<text x="365" y="106" fill="#7fb0cc" font-size="12" text-anchor="middle">N barrels — recycled buffers (Law 2)</text>
</g>
<!-- 1: writer -->
<rect x="540" y="170" width="150" height="120" rx="10" fill="url(#chip)" stroke="#2b6f96"/>
<text x="615" y="220" fill="#eaf6ff" font-size="15" font-weight="700" text-anchor="middle">writer</text>
<text x="615" y="244" fill="#9fc9e0" font-size="12" text-anchor="middle">pwrite @ cursor</text>
<text x="615" y="262" fill="#9fc9e0" font-size="12" text-anchor="middle">concurrent (Law 4)</text>
<text x="615" y="158" fill="#7fb0cc" font-size="12" text-anchor="middle">1</text>
<!-- seal tail (hot/serial) -->
<rect x="760" y="120" width="380" height="320" rx="12" fill="url(#hot)" stroke="#a84747"/>
<text x="950" y="150" fill="#ffd9d9" font-size="15" font-weight="700" text-anchor="middle">ArrowIpcSink::finish — ONE thread</text>
<text x="950" y="182" fill="#ffcaca" font-size="13" text-anchor="middle">sort all rows by (path, chunk_seq) ← sort_ms</text>
<text x="950" y="210" fill="#ffcaca" font-size="13" text-anchor="middle">2nd full materialisation: lookup sub-index</text>
<text x="950" y="234" fill="#ffcaca" font-size="13" text-anchor="middle">build fst trie (every distinct path)</text>
<text x="950" y="258" fill="#ffcaca" font-size="13" text-anchor="middle">write manifest + 8+8B footer + sync_all</text>
<text x="950" y="300" fill="#ff9a9a" font-size="13" font-weight="700" text-anchor="middle">⟶ footer_seal bench: seal_ms / seal_mrows_s</text>
<text x="950" y="330" fill="#ffcaca" font-size="12" text-anchor="middle">scales with TOTAL CHUNK COUNT, runs AFTER</text>
<text x="950" y="348" fill="#ffcaca" font-size="12" text-anchor="middle">the blob pipeline has already drained</text>
<text x="950" y="392" fill="#ffd9d9" font-size="12" text-anchor="middle">read side (cold): every locate_file re-reads</text>
<text x="950" y="410" fill="#ffd9d9" font-size="12" text-anchor="middle">manifest + both sections ⟶ random_lookup,</text>
<text x="950" y="428" fill="#ffd9d9" font-size="12" text-anchor="middle">prefix_meta, decompress_subset benches</text>
<!-- arrows -->
<line x1="190" y1="230" x2="266" y2="170" stroke="#9fc9e0" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="190" y1="230" x2="266" y2="230" stroke="#9fc9e0" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="190" y1="230" x2="266" y2="300" stroke="#9fc9e0" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="464" y1="152" x2="536" y2="210" stroke="#9fc9e0" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="464" y1="230" x2="536" y2="230" stroke="#9fc9e0" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="464" y1="308" x2="536" y2="250" stroke="#9fc9e0" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="690" y1="230" x2="756" y2="230" stroke="#ff9a9a" stroke-width="3" marker-end="url(#arrow)"/>
<text x="40" y="500" fill="#7fb0cc" font-size="12">B1 subindex_write times the per-row Arrow IPC serialise + accumulate_lookup copy · B2 footer_seal times the red box · B3/B4/B5 time the cold read path.</text>
</svg>