~bigbes/tarantool-protobuf: 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 46045da1d9330db68d0e8210ff0ba4ae2c0885dbview raw patch

Parent(s): 89cc5008

2 changed file(s)

FileStatus+
runtime/pb/codec.lua M +189 -2
runtime/pb/init.lua M +9 -4