Skip to content

v0.1.7: the store path caps throughput at a few hundred MiB/s — write-once packs, page size or fewer stored bytes #218

Description

@yifanxuaaa

Status: Proposal for the next optimization round; not an implemented capability and not a performance claim. A Store-format change needs an owner ruling before it is implemented — see "Boundaries".

What the measurements say

The store half, not construction and not the wire, is what caps throughput. All numbers below are from docs/roadmap/0.1/0.1.7/evidence/, one sample per arm, on a host that was not idle (load ~6–7 of 14 cores).

Product phase split, measure_ingest, 512 MiB incompressible:

phase time rate share
content construct (C1) 0.829 s 617.66 MiB/s 19%
accept (C2 save) 3.095 s 165.43 MiB/s 71%
publication commit 0.419 s 10%
end to end 4.349 s 117.73 MiB/s 100%

Counters: inserted=27845 packs_created=2229 pack_appends=11682 commits=13913, Store 520.7 MiB for a 512 MiB payload (~5.2 appends per pack).

The same code path with content that deduplicates stores 0.3 MiB and runs accept at 2213 MiB/s and the save at 1778 MiB/s, with construction unchanged at 641.99 MiB/s. The save half is proportional to stored bytes, not to CPU.

External SQLite mimic, same declared profile (MEMORY journal, synchronous=OFF, temp_store=MEMORY, busy_timeout=0), no product code, 512 MiB stored per arm:

pattern rate
sequential 250 KiB BLOB inserts, 4 KiB pages 209.3 MiB/s
sequential 1 MiB blobs 242.3 MiB/s
sequential 250 KiB blobs, 16 KiB pages 272.9 MiB/s
one append to a growing blob 150.3 MiB/s
aggressive grow-to-2x (~5 appends) 46.2 MiB/s
same, commit cadence 16x coarser 50.9 MiB/s

So the engine's ceiling for this shape is a few hundred MiB/s, rewriting a growing BLOB costs 2–5x, a larger page buys ~30%, and commit cadence only ~10%. The product's 165 MiB/s sits inside that band, which is why this is a placement/format question rather than a layer-above question.

Levers, with prices

  1. Write-once packs — never append to a placed pack; one INSERT per sealed pack, or one pack per sealed group. In the mimic this is 46 -> 209 MiB/s. Price: physical layout and the Store hash change, so it is an owner ruling. The #209 format round produced a related change (−1.55 s commit_ns, −1.30 s operation on stride10, every check green) and it was reverted by owner decision; that ruling is the precedent this issue must resolve first.
  2. Larger pages (16 KiB) — ~30% in the mimic (209 -> 273 MiB/s). Also a Store-format change.
  3. Fewer stored bytes — the dedup/delta path already exploits this; the lever is real (60x less storage, ~60x faster save), so representation selection and reuse coverage remain live work.
  4. v0.1.7: the multi-writer transaction cadence costs the single-writer save path 2.06x on stride10 (42x more commits) #209's open remainder — stride10 is 24.72 s against 16.36 s for the pre-multi-writer model; the commit cadence is load-bearing for the second writer, so this is not a revert.

Refuted levers, so nobody retries them

  • More writers: the budget ladder plateaus at 2–4 and falls at 8 (125.29 / 142.68 / 140.99 / 132.76 MiB/s at 1/2/4/8).
  • A faster AEAD: the transport is 802 MiB/s (one stream) and 1556 MiB/s (two) against a ~100 MiB/s route — already 5–8x faster than what it feeds.
  • Faster construction: 617 MiB/s against a 165 MiB/s save.

The instrument this round needs first

The product reports no pages-written-per-commit or write-amplification counter, so any placement change would be pre-registered blind: the mimic bounds the engine, but the product's own amplification is only inferable from pack_appends / packs_created. Before a format ruling is requested, add that observation (pages written per commit, and stored-bytes written per stored byte) so the treatment's mechanism is measurable in-product.

Boundaries

  • Do not retune or relabel historical arms and receipts; #209 stays its own issue with its own evidence.
  • Preserve authentication, bounds, failure/visibility semantics and the single construction producer per ordinary operation.
  • No new durability, WAL or fsync work; no third-party patching.
  • Every measurement row states its cache state, its interference and its gaps; one sample per case per arm.

Acceptance for this issue

  • The instrument exists and reports amplification on a real save, with the counters named and bounded.
  • An owner ruling records which of levers 1–3 is authorized, with the format-compatibility consequence stated (including what an existing schema-8 Store does).
  • The authorized lever is implemented with matched arms: identical canonical results and refusal behaviour, committed Store accounting, and a measured change in the instrument's own units.
  • Every non-passing row, every unrun route and every budget class is reported as plainly as a PASS.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions