~bigbes/tarantool-protobuf: 035b2adb

codegen: CHARS[_len] lookup replaces string.char(_len) at length-prefix sites (2ri)

Profile attributed 39% of Person_encode's trace share (~28% of total) to a
single line emitting `string.char(_len)` at every inlined length-prefix
site. The `_len` argument is rarely a compile-time constant (lengths come
from user data), so the JIT can't fold the C-function call, and the cost
compounds — the 1KB Person fixture fires ~30 length-prefix sites per
encode.

Replace with a 256-entry lookup table `wire.CHARS` (built once at module
load, byte i -> string.char(i)). Codegen header now emits
`local CHARS = wire.CHARS` alongside the other hot-path localizers; the
single emit site in `emitInlineLenPrefix` swaps `string.char(_len)` for
`CHARS[_len]`. Parity is by construction — both return the same interned
1-byte string.

Tests: 752/752 pass. Bench (work.lab.local, median of 3, hello.Person
encode): 10B +4.7%, 1KB +16.8%, 10KB +21.1%, 100KB +34.2%, proto2 mid
+11.1%. Decode unchanged. See bench/PERF_LOG.md 2026-05-24 2ri entry.

Closes lkz and 86g (ffi.new buffer rewrite paths) — separate hand-spike
of that shape regressed 0.31x-0.77x across all sizes; the perceived
buffering inefficiency wasn't there, and 2ri captured the single hottest
line. Remaining encode-perf headroom is c0i (C-runtime backend).

Eugene Blikh <bigbes@gmail.com> — 2026-05-24 16:54:18 UTC

Commit 035b2adbf9bf91e4cfc031aa1141ab75d0bb30f1view raw patch

Parent(s): 2df86386

24 changed file(s)

FileStatus+
.beads/interactions.jsonl M +3
.beads/issues.jsonl M +2 -1
bench/PERF_LOG.md M +76
cmd/protoc-gen-tarantool/internal/gen/gen.go M +3
cmd/protoc-gen-tarantool/internal/gen/inline.go M +1 -1
examples/expected/full/c_int64/c_int64_pb.lua M +1
examples/expected/full/c_nested/c_nested_pb.lua M +5 -4
examples/expected/full/c_repeated/c_repeated_pb.lua M +14 -13
examples/expected/full/conformance/conformance_pb.lua M +20 -19
examples/expected/full/hello/hello_pb.lua M +29 -28
examples/expected/full/proto2_basic/proto2_basic_pb.lua M +13 -12
examples/expected/full/protobuf_test_messages/proto2/test_messages_proto2_pb.lua M +83 -82
examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua M +100 -99
examples/expected/full/quickstart/quickstart_pb.lua M +3 -2
examples/expected/runtime/c_int64/c_int64_pb.lua M +1
examples/expected/runtime/c_nested/c_nested_pb.lua M +1
examples/expected/runtime/c_repeated/c_repeated_pb.lua M +1
examples/expected/runtime/conformance/conformance_pb.lua M +1
examples/expected/runtime/hello/hello_pb.lua M +1
examples/expected/runtime/proto2_basic/proto2_basic_pb.lua M +1
examples/expected/runtime/protobuf_test_messages/proto2/test_messages_proto2_pb.lua M +1
examples/expected/runtime/protobuf_test_messages/proto3/test_messages_proto3_pb.lua M +1
examples/expected/runtime/quickstart/quickstart_pb.lua M +1
runtime/pb/wire.lua M +10