8014163c
codec: precompute per-field writers for singular scalar/enum/message (~+50% small-msg encode)
pb.finalize_message now calls codec.compile_writers(desc), which
attaches `f._writer` to each field whose shape we can specialize:
singular scalar, singular enum, singular message — i.e. not maps,
not repeated, not oneof. Each writer is a monomorphic closure that
knows its tag bytes, encoder function, and default predicate. The
encode_message hot loop calls writer(data, out) per field and only
falls through to encode_field for shapes we haven't specialized.
This eliminates the per-field `encode_field` dispatch chain
(kind/proto_type branch + `is_default_scalar` call), which was the
source of the remaining trace bridges in runtime mode (codec.lua:41
and codec.lua:110 in `make jit-trace` output).
Effect (bench/bench.lua, hello.Person):
runtime/10B encode: 5.0 → 8.1 MB/s (+62%)
runtime/100B encode: 48.2 → 75.2 MB/s (+56%)
runtime/1KB encode: 49.5 → 56.1 MB/s (+13%)
runtime/10KB+ encode: unchanged (dominated by repeated-field
iteration — not yet specialized)
full mode encode: +10% across small sizes (writer closures also
help when codegen calls back into the runtime)
decode: unchanged
alloc/op: unchanged (bench-compare clean)
bridges across 10 jit-trace runs: 7 → 4
Eugene Blikh <bigbes@gmail.com> — 2026-05-15 10:59:11 UTC
Commit 8014163c25e3b4c8aa61f04b4412b656f54ba495 —
view raw patch
Parent(s):
9f3bfb8f
| File | Status | + | − |
|---|---|---|---|
runtime/pb/codec.lua
|
M | +117 | -1 |
runtime/pb/init.lua
|
M | +6 |