diff --git a/bench/PERF_LOG.md b/bench/PERF_LOG.md index 3f9de725a486655d4e9281a604ac696279c105c1..76b46a4cb1e73098da313cc636235033e3d235d1 100644 --- a/bench/PERF_LOG.md +++ b/bench/PERF_LOG.md @@ -84,6 +84,54 @@ --- +## 2026-05-18 — u39: table.new(0, N) for result tables (REVERTED) + +**Task:** [tarantool-protobuf-u39] Decoder: emit `table.new(0, N)` for +result tables. The thesis was that pre-sizing the result table's hash +part to the message's field count would avoid the rehash that +fresh-`{}` tables pay as fields are added. + +**Change attempted:** Header now `require('table.new')` with a pcall +fallback so plain-Lua loads still work; `emitInlineDecode` allocates the +result via `table_new(0, len(m.Fields))` instead of `{}`. 745/745 tests +pass. JIT 37/37. + +**Bench (Person full decode, msgs/s, median-of-3 vs post-cch):** + +| size | post-cch | u39 | Δ | +|-------|-----------|-----------|----------| +| 10B | 2,495,633 | 2,111,197 | **-15.4%** | +| 100B | 2,131,196 | 1,754,540 | **-17.7%** | +| 1KB | 115,310 | 117,270 | +1.7% | +| 10KB | 15,831 | 15,627 | -1.3% | +| 100KB | 1,620 | 1,617 | -0.2% | + +**Outcome: reverted.** Small-payload decode collapsed. The +`table_new(0, N)` call (through an upvalue, with arguments) is +several times the cost of a `{}` literal, and at 10B/100B the decode +loop only populates 2-4 fields — well under the LuaJIT default hash +size where the first rehash would land. The rehash savings never +materialize because the small case doesn't reach them; meanwhile the +extra call cost is paid every decode. + +Large payloads (1KB+) saw no meaningful gain either — by then decode +time is dominated by tag decoding, string extraction, and varint +parsing, not table allocation. The `drm` memory entry already +documented "136 B alloc floor is not the throughput bottleneck"; this +result confirms it from the opposite direction. + +**Lesson:** allocation-shape optimizations are only worth it when the +workload spends real time in allocation. The bench corpus does not +exercise that mode; if a workload ever does (lots of tiny messages, or +messages with very wide field sets), revisit then. Sticking with `{}` +also keeps generated code compatible with plain Lua (no LuaJIT-only +require) — small platform-portability win. + +**Commit:** none — change reverted. PERF_LOG entry is the only +artifact. + +--- + ## 2026-05-18 — cch: local counter for repeated-field append **Task:** [tarantool-protobuf-cch] Decoder: use local counter instead of