bench: C-acceleration spike — measure four Lua↔C boundaries Adds bench/c_accel/ with hello.Person codecs at four boundary strategies and a harness comparing them across 10B–100KB: S1 pure Lua (full mode) — existing baseline S2 prim.c + prim_ffi.lua — per-primitive FFI calls S3 generic_codec.c — one C call per message, descriptor-walking S4 person_codec.c — hand-written, no dispatch, upper bound Plus ffi_probe.lua, a microbenchmark decomposing FFI call cost. Headline numbers (×L = speedup vs pure-Lua full mode): ENCODE S2 S3 S4 10B 0.99 3.29 3.79 100B 0.93 3.12 3.46 1KB 0.82 5.33 4.94 10KB 0.60 3.53 2.86 100KB 0.63 3.49 2.85 DECODE S2 S3 S4 10B 0.29 2.59 2.54 100B 0.33 2.94 2.95 1KB 0.39 7.22 7.62 10KB 0.38 9.64 10.23 100KB 0.37 10.87 11.33 S3 lands within ±15% of S4 at every size and beats it on encode at 1KB+: the descriptor-walking loop is uniformly branch-predictable; hand-written has more divergent per-field paths. S2 loses to pure Lua at every size ≥1KB on encode and at every size on decode. FFI cost decomposition (ffi_probe.lua): bare FFI call into ffi.load lib 33 ns pointer-returning FFI 73 ns + v_out[0] read + tonumber 118 ns ffi.C.memcmp (for comparison) 60 ns ffi.cast(const uint8_t*, str) 156 ns ffi.string(p, 32) 23 ns pure-Lua varint decode 75 ns read_varint in tight traced loop 59 ns (floor) Per-call FFI dispatch into a ffi.load'd lib is ~60–75 ns — the same order of magnitude as pure-Lua varint decode. The "win" from going to C only materializes when you cross the boundary ONCE per message, not per primitive. C encode plateaus at ~2.5–2.9 GB/s from 1KB upward; bottleneck moves to Lua table reads and output string allocation. C decode hits 2.5 GB/s at 100KB, while pure-Lua decode hits a per-byte cliff (158 k msg/s @ 1KB → 2.3 k @ 100KB). Architecture implication for pf6: the generic C runtime (ra6) gets the full perf envelope; codegen-emitted per-message C (c0i) earns ≤15% headroom and goes the wrong way at scale. Per-primitive FFI is a non-starter. Required impl pattern in any future ra6: cache per-field stack indices for repeated/packed arrays for the duration of decode_message — the naive lazy-getfield variant was 2× slower than hand-written at 100KB (see bench/c_accel/README.md). beads-tarantool-protobuf-04c