46045da1
codec: precompute per-field readers (runtime decode +10–17%)
Mirror of compile_writers on the decode side: pb.finalize_message now also calls codec.compile_readers(desc), attaching `f._reader` to each field whose shape can be specialized — singular scalar/enum/message and repeated scalar/enum/message (packed and unpacked). Each reader has signature (buf, pos, wt, result) -> new_pos and bakes in the field name, decode function, packed-detection, list bookkeeping, nested-message merge rules, and oneof sibling clearing. The decode_message hot loop becomes: id, wt, pos = decode_tag(buf, pos) f = fbi[id] if f and f._reader then pos = f._reader(buf, pos, wt, result) else /* existing per-kind dispatch — map fields only */ end Forward declaration `local decode_msg` so reader closures captured at finalize-time can refer to it; the later `decode_msg = function...` fills the upvalue. Effect (bench/bench.lua, hello.Person): runtime/100B decode: 246 → 272 MB/s (+11%) runtime/1KB decode: 122 → 144 MB/s (+17%) runtime/10KB decode: 176 → 200 MB/s (+13%) runtime/100KB decode: 180 → 210 MB/s (+17%) full mode decode: ~flat (already maximally inlined by codegen) encode: unchanged alloc/op: unchanged (bench-compare clean) bridges across 10 jit-trace runs: 3 → 2 Runtime mode decode is now within ~10–15% of full mode across all sizes, vs 24–28% gap before this commit.
Eugene Blikh <bigbes@gmail.com> — 2026-05-15 11:07:56 UTC
Commit 46045da1d9330db68d0e8210ff0ba4ae2c0885db —
view raw patch
Parent(s):
89cc5008
| File | Status | + | − |
|---|---|---|---|
runtime/pb/codec.lua
|
M | +189 | -2 |
runtime/pb/init.lua
|
M | +9 | -4 |