.nornir/assets/lgz_flow.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 720" 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="rail" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#173d57"/><stop offset="1" stop-color="#0c2438"/>
</linearGradient>
<linearGradient id="slot" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#123448"/><stop offset="1" stop-color="#0a2032"/>
</linearGradient>
<marker id="ah" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0 0 L10 5 L0 10 z" fill="#6fd3f5"/>
</marker>
<marker id="ahc" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
<path d="M0 0 L10 5 L0 10 z" fill="#ff7a7a"/>
</marker>
</defs>
<rect x="0" y="0" width="1180" height="720" fill="url(#board)"/>
<g stroke="#143a52" stroke-width="1"><line x1="0" y1="74" x2="1180" y2="74"/><line x1="0" y1="676" x2="1180" y2="676"/></g>
<g fill="#16415c"><circle cx="40" cy="38" r="2"/><circle cx="1140" cy="38" r="2"/><circle cx="40" cy="694" r="2"/><circle cx="1140" cy="694" r="2"/></g>
<text x="40" y="42" fill="#eaf6ff" font-size="22" font-weight="700">lgz</text>
<text x="96" y="42" fill="#9fc9e0" font-size="15">multi-member gzip decode — member/flush scan → self-dispatch DEFLATE workers → ordered/positional write (<tspan fill="#bfe6ff" font-weight="700">~7.8/12 cores</tspan>)</text>
<g font-size="12">
<line x1="700" y1="60" x2="740" y2="60" stroke="#6fd3f5" stroke-width="3" marker-end="url(#ah)"/>
<text x="746" y="64" fill="#cfe6f5">parallel dataflow</text>
<line x1="900" y1="60" x2="940" y2="60" stroke="#ff7a7a" stroke-width="2.5" stroke-dasharray="5 4" marker-end="url(#ahc)"/>
<text x="946" y="64" fill="#cfe6f5">serial fallback (format-forced)</text>
</g>
<!-- INPUT -->
<rect x="34" y="292" width="150" height="150" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="109" y="318" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">.gz input</text>
<text x="109" y="336" fill="#9fc9e0" font-size="10.5" text-anchor="middle">file (mmap) or stdin</text>
<rect x="52" y="352" width="114" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="109" y="369" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">memmap2::Mmap</text>
<rect x="52" y="384" width="114" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="109" y="401" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">gzip 1f 8b 08</text>
<text x="109" y="428" fill="#7fa8c4" font-size="9.5" text-anchor="middle">bin/lgz.rs:main</text>
<!-- SCAN -->
<rect x="228" y="128" width="196" height="200" rx="11" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="326" y="152" fill="#eaf6ff" font-size="14" font-weight="700" text-anchor="middle">member scan</text>
<text x="326" y="169" fill="#9fc9e0" font-size="10" text-anchor="middle">concatenated-.gz fast path</text>
<rect x="246" y="182" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="326" y="196" fill="#bfe6ff" font-size="9.2" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">find_gzip_members</text>
<text x="326" y="207" fill="#9fc9e0" font-size="8.5" text-anchor="middle">_parallel · gatling_for_each</text>
<rect x="246" y="220" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="326" y="234" fill="#bfe6ff" font-size="9.2" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">ISIZE trailer → sizes</text>
<text x="326" y="245" fill="#9fc9e0" font-size="8.5" text-anchor="middle">prefix-sum → byte offsets</text>
<text x="326" y="272" fill="#86b3cc" font-size="9.2" text-anchor="middle">≥2 members ⇒ fast path;</text>
<text x="326" y="286" fill="#86b3cc" font-size="9.2" text-anchor="middle">else fall to flush split ↓</text>
<text x="326" y="312" fill="#7fa8c4" font-size="9" text-anchor="middle">speculative.rs:471 · lgz.rs:200</text>
<rect x="228" y="392" width="196" height="200" rx="11" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="326" y="416" fill="#eaf6ff" font-size="14" font-weight="700" text-anchor="middle">flush split</text>
<text x="326" y="433" fill="#9fc9e0" font-size="10" text-anchor="middle">single-member streaming</text>
<rect x="246" y="446" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="326" y="460" fill="#bfe6ff" font-size="9.2" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">producer: read+carry</text>
<text x="326" y="471" fill="#9fc9e0" font-size="8.5" text-anchor="middle">200 MB chunk, strip header</text>
<rect x="246" y="484" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="326" y="498" fill="#bfe6ff" font-size="9.2" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">split_chunk 00 00 FF FF</text>
<text x="326" y="509" fill="#9fc9e0" font-size="8.5" text-anchor="middle">full-flush ⇒ independent segs</text>
<text x="326" y="536" fill="#86b3cc" font-size="9.2" text-anchor="middle">sync-flush ⇒ 1 seg (windowed);</text>
<text x="326" y="550" fill="#86b3cc" font-size="9.2" text-anchor="middle">no boundary ⇒ fallback ↓</text>
<text x="326" y="576" fill="#7fa8c4" font-size="9" text-anchor="middle">chunk.rs:29 · lgz.rs producer</text>
<!-- WORKERS -->
<rect x="474" y="248" width="204" height="224" rx="12" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="576" y="272" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">N workers</text>
<text x="576" y="289" fill="#9fc9e0" font-size="10" text-anchor="middle">self-dispatch, no barrier</text>
<g font-family="'DejaVu Sans Mono',monospace">
<rect x="494" y="302" width="164" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="576" y="319" fill="#bfe6ff" font-size="9.5" text-anchor="middle">decode member i</text>
<rect x="494" y="334" width="164" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="576" y="351" fill="#bfe6ff" font-size="9.5" text-anchor="middle">decode_segment_into_hint</text>
<rect x="494" y="366" width="164" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="576" y="383" fill="#bfe6ff" font-size="9.5" text-anchor="middle">flate2 / linflate core</text>
</g>
<text x="576" y="414" fill="#86b3cc" font-size="9.5" text-anchor="middle">atomic fetch_add claims next</text>
<text x="576" y="429" fill="#86b3cc" font-size="9.5" text-anchor="middle">ISIZE-presized recycled buffer</text>
<text x="576" y="444" fill="#7CFFB2" font-size="9.5" text-anchor="middle">warm buffer pool → 0 steady alloc</text>
<text x="576" y="462" fill="#7fa8c4" font-size="9" text-anchor="middle">gatling_ordered.rs:177</text>
<!-- SINK -->
<rect x="728" y="248" width="196" height="224" rx="12" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="826" y="272" fill="#eaf6ff" font-size="14" font-weight="700" text-anchor="middle">ordered sink</text>
<text x="826" y="289" fill="#9fc9e0" font-size="10" text-anchor="middle">stream-order, bounded reorder</text>
<rect x="746" y="302" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="826" y="316" fill="#bfe6ff" font-size="9.2" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">run_ordered_sink</text>
<text x="826" y="327" fill="#9fc9e0" font-size="8.5" text-anchor="middle">cap = 2×workers, permit pool</text>
<rect x="746" y="340" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="826" y="354" fill="#bfe6ff" font-size="9.2" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">WriteSink::emit(seq)</text>
<text x="826" y="365" fill="#9fc9e0" font-size="8.5" text-anchor="middle">recycle warm buf → pool</text>
<text x="826" y="392" fill="#ffcf6f" font-size="9.2" text-anchor="middle">-o file: positional pwrite</text>
<rect x="746" y="402" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="826" y="416" fill="#bfe6ff" font-size="9.2" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">write_segments_positional</text>
<text x="826" y="427" fill="#9fc9e0" font-size="8.5" text-anchor="middle">workers pwrite own offset</text>
<text x="826" y="454" fill="#7fa8c4" font-size="9" text-anchor="middle">parwrite.rs:191</text>
<!-- OUTPUT -->
<rect x="974" y="292" width="150" height="150" rx="11" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="1049" y="318" fill="#eaf6ff" font-size="14" font-weight="700" text-anchor="middle">output</text>
<text x="1049" y="336" fill="#9fc9e0" font-size="10" text-anchor="middle">decompressed bytes</text>
<rect x="992" y="352" width="114" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="1049" y="369" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">-o file (pwrite)</text>
<rect x="992" y="384" width="114" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="1049" y="401" fill="#bfe6ff" font-size="9.5" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">stdout (ordered)</text>
<text x="1049" y="428" fill="#7fa8c4" font-size="9.5" text-anchor="middle">CRC32 + ISIZE verified</text>
<!-- FLOW PATHS -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M184 340 C 208 300, 210 240, 226 226" marker-end="url(#ah)"/>
<path d="M184 400 C 208 440, 210 480, 226 490" marker-end="url(#ah)"/>
<path d="M424 230 C 448 260, 452 300, 472 320" marker-end="url(#ah)"/>
<path d="M424 496 C 448 440, 452 400, 472 380" marker-end="url(#ah)"/>
<path d="M678 360 H726" marker-end="url(#ah)"/>
<path d="M924 360 C 948 360, 950 366, 972 366" marker-end="url(#ah)"/>
</g>
<!-- permit recycle back path -->
<path d="M728 440 C 690 470, 660 470, 660 468" stroke="#7CFFB2" stroke-width="2" fill="none" stroke-dasharray="4 3" marker-end="url(#ah)"/>
<text x="700" y="486" fill="#7CFFB2" font-size="9" text-anchor="middle">permit / buf recycle</text>
<!-- FALLBACK RAIL -->
<rect x="228" y="612" width="696" height="46" rx="9" fill="#0a2032" stroke="#8a4a4a" stroke-width="1.5" stroke-dasharray="4 3"/>
<text x="246" y="634" fill="#ff9c9c" font-size="12" font-weight="700">serial fallback</text>
<text x="344" y="631" fill="#e7bcbc" font-size="10">no flush boundary in whole file ⇒ decode_concatenated_members → speculative_decode (trailer-checked) → single-thread flate2</text>
<text x="344" y="648" fill="#b98a8a" font-size="9" font-family="'DejaVu Sans Mono',monospace">lgz.rs:666 fallback · gzip single-member is serial-by-format (one LZ77 window, no independent split point)</text>
<path d="M326 592 V610" stroke="#ff7a7a" stroke-width="2.5" fill="none" stroke-dasharray="5 4" marker-end="url(#ahc)"/>
<path d="M924 635 C 990 635, 1049 560, 1049 444" stroke="#ff7a7a" stroke-width="2.5" fill="none" stroke-dasharray="5 4" marker-end="url(#ahc)"/>
</svg>