~bigbes/tarantool

tarantool-protobuf

2ffc6ebd58b1eb374c43e75566a3fecb1cbf20ef — Eugene Blikh 3 months ago 51f1963
wkt: split length-prefix emission to drop per-field concat

Apply the split-emit pattern from ac9b9c1 (inline.go + codec.lua) to the
WKT hand-rolled encoders. Replace `wire.encode_len(body)` — which
allocates `varint(#body) .. body` — with three out slots (tag, varint
length, body) wherever the result feeds a `table.concat(out)`
accumulator. For StringValue/BytesValue (whose encoders return a single
string and can't be split), inline encode_len's chain so LuaJIT folds
tag + varint + body into one multi-concat instead of two sequential
concats. Same final wire bytes.

Touched sites: struct_encode (split the outer entry wrap, inline the
inner key/value chain), list_encode, any_encode (type_url, value),
fieldmask_encode, and the WRAPPERS LEN-typed encoders.

The struct_encode inner entry stays a single chain rather than fanning
out into more `out` slots — eight slots per Struct entry regressed
B/op and gave no encode win on the wkt-event shape; three slots match
the codec.lua nested-message pattern and land the speedup.

bench/shapes (wkt-event encode, median across 4 runs):
  full:    125895 -> 129000 msgs/s (+2.5%)
  runtime: 115231 -> 120000 msgs/s (+4%)

make test 509/509, make jit-trace 23/23, docker conformance binary
1478/0 (unexpected), text suite clean.
1 files changed, 32 insertions(+), 10 deletions(-)

M runtime/pb/wkt.lua
M runtime/pb/wkt.lua => runtime/pb/wkt.lua +32 -10
@@ 202,9 202,19 @@ for _, spec in ipairs(WRAPPERS) do
    local decode = wire[dec_fn]
    local tag = TAG_BY_WIRE[wt]

    M[name .. '_encode'] = function(v)
        if v == nil or is_default(v) then return '' end
        return tag .. encode(v)
    if wt == wire.WIRE_LEN then
        -- StringValue / BytesValue: skip encode_len's `varint(#v) .. v` and
        -- let LuaJIT fold tag + varint + body into a single multi-concat
        -- instead of two sequential concats.
        M[name .. '_encode'] = function(v)
            if v == nil or is_default(v) then return '' end
            return tag .. wire.encode_varint(#v) .. v
        end
    else
        M[name .. '_encode'] = function(v)
            if v == nil or is_default(v) then return '' end
            return tag .. encode(v)
        end
    end

    M[name .. '_decode'] = function(buf)


@@ 321,12 331,18 @@ struct_encode = function(t)
    -- Each Struct entry: tag(1, LEN)=0x0a, entry_len, entry_payload
    -- Entry payload: tag(1, LEN)=0x0a + key_len_prefixed_bytes
    --              + tag(2, LEN)=0x12 + value_len_prefixed_bytes
    -- Split the outer entry wrap so the final `table.concat` joins entries
    -- in one pass (matches the codec.lua nested-message pattern). The inner
    -- entry stays a single multi-concat: it's cheaper than three more out
    -- slots once the entry is small.
    for k, v in pairs(t) do
        local key_str = type(k) == 'string' and k or tostring(k)
        local entry = '\x0a' .. wire.encode_len(key_str)
                   .. '\x12' .. wire.encode_len(value_encode(v))
        local val_body = value_encode(v)
        local entry = '\x0a' .. wire.encode_varint(#key_str) .. key_str
                   .. '\x12' .. wire.encode_varint(#val_body) .. val_body
        n = n + 1; out[n] = '\x0a'
        n = n + 1; out[n] = wire.encode_len(entry)
        n = n + 1; out[n] = wire.encode_varint(#entry)
        n = n + 1; out[n] = entry
    end
    return table.concat(out)
end


@@ 335,8 351,10 @@ list_encode = function(t)
    if t == nil then return '' end
    local out, n = {}, 0
    for i = 1, #t do
        local body = value_encode(t[i])
        n = n + 1; out[n] = '\x0a'
        n = n + 1; out[n] = wire.encode_len(value_encode(t[i]))
        n = n + 1; out[n] = wire.encode_varint(#body)
        n = n + 1; out[n] = body
    end
    return table.concat(out)
end


@@ 464,12 482,14 @@ any_encode = function(v)
    local type_url = v.type_url
    if type_url ~= nil and type_url ~= '' then
        n = n + 1; out[n] = '\x0a'                          -- field 1, LEN
        n = n + 1; out[n] = wire.encode_len(type_url)
        n = n + 1; out[n] = wire.encode_varint(#type_url)
        n = n + 1; out[n] = type_url
    end
    local value = v.value
    if value ~= nil and value ~= '' then
        n = n + 1; out[n] = '\x12'                          -- field 2, LEN
        n = n + 1; out[n] = wire.encode_len(value)
        n = n + 1; out[n] = wire.encode_varint(#value)
        n = n + 1; out[n] = value
    end
    return table.concat(out)
end


@@ 554,8 574,10 @@ local function fieldmask_encode(v)
    if v == nil or #v == 0 then return '' end
    local out, n = {}, 0
    for i = 1, #v do
        local s = v[i]
        n = n + 1; out[n] = '\x0a'  -- field 1, LEN
        n = n + 1; out[n] = wire.encode_len(v[i])
        n = n + 1; out[n] = wire.encode_varint(#s)
        n = n + 1; out[n] = s
    end
    return table.concat(out)
end