From d6570ec6e105e3986ee544a06804e44649afc356 Mon Sep 17 00:00:00 2001 From: Eugene Blikh Date: Fri, 15 May 2026 17:26:12 +0300 Subject: [PATCH] docs: PLAN.md lazy perf numbers after SoA refactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lazy entry's perf claims were written against the per-segment-table implementation. Update with the post-SoA numbers — passthrough 1.6–1.9×, sparse read 0.90–1.16×, mutate+reencode 1.09–1.26× — and drop the caveat about sparse-read losing on flat shapes (no longer true). --- PLAN.md | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/PLAN.md b/PLAN.md index c4906c48abc72f1ad455f670b3f00c903dd4f611..68f0534af11119e07b1cfc8d39f0d51d98e57697 100644 --- a/PLAN.md +++ b/PLAN.md @@ -194,25 +194,21 @@ fiber and bridges client ↔ handler via `fiber.channel`. All four flavors `:encode` all compile with no fatal aborts. Workload characteristics (from `tarantool bench/lazy_bench.lua`, - Person at 1KB / 10KB / 100KB): - - **Passthrough re-encode** is the headline win: **1.0–1.5×** + Person at 1KB / 10KB / 100KB, after the SoA index refactor): + - **Passthrough re-encode** is the headline win: **1.6–1.9×** faster than eager decode→encode across all sizes and both modes. Untouched views never re-walk the wire. - - **Sparse read** (`:get` two top-level fields) is **0.60–0.77× - of eager** on the emails-heavy Person shape. Index-build - allocates one segment table per wire entry, and for messages - that scale via repeated leaves (no deeply-nested subtrees that - `skip_field` can vault over), that allocation cost cancels the - decode-skip savings. Lazy still wins this shape on payloads - dominated by nested submessages — that case isn't represented - in the current bench. - - **Mutate-then-reencode** is **0.81–1.07× of eager**; ~break-even - to slight loss on the same flat shape. Both decode+set+encode - and decode_lazy+set+encode walk the full byte range; lazy - splices substrings, eager re-emits per-field. - The honest framing: lazy is a *byte-passthrough* optimization; - it's not a universal speedup. Use it when you decode, touch few - fields, and re-encode — the common proxy/router shape. + - **Sparse read** (`:get` two top-level fields) is **0.90–1.16× + of eager**: break-even at small sizes, slight win at 100KB + (especially in runtime mode where eager pays more dispatch + cost). Earlier 0.60–0.77× regression came from one Lua table + per wire entry; replacing with parallel int arrays closed the + allocation gap. + - **Mutate-then-reencode** is **1.09–1.26× of eager**; the + per-field splice path now consistently beats full re-encode. + The honest framing: lazy is a *byte-passthrough* optimization + that also handles sparse reads at parity. Best fit: proxy / + router shapes that decode, touch a few fields, and re-encode. ### M7 — Developer ergonomics