Skip to content

perf: Pre-size variadic command buffers from their arguments#2865

Open
iliaal wants to merge 1 commit into
phpredis:developfrom
iliaal:perf/presize-variadic-builders
Open

perf: Pre-size variadic command buffers from their arguments#2865
iliaal wants to merge 1 commit into
phpredis:developfrom
iliaal:perf/presize-variadic-builders

Conversation

@iliaal

@iliaal iliaal commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Extends the MSET pre-sizing (#2861) to the shared multi-argument builders, which previously regrew the command smart_string one 4KB page at a time as their append loop ran. A shared helper sums an upper-bound RESP frame size over the arguments in a read-only pre-pass and reserves the buffer once. It only reads types and lengths, so it cannot change the bytes emitted, and an under-estimate falls back to normal growth.

Covers redis_key_varval_cmd (SADD/SREM/RPUSH/LPUSH/ZREM), gen_key_arr_cmd, gen_vararg_cmd, redis_mget_cmd, and redis_hmset_cmd. gen_varkey_cmd (DEL/SUNION/SINTER) is a follow-up; its single-array and timeout branching has no clean reservation point.

Verified on PHP 8.4 across high-arity and large-payload calls with prefix and serializer combinations: no leaks, 25 project suite methods pass.

Extends the MSET pre-sizing (phpredis#2861) to the shared multi-argument builders
so a high-arity or large-payload call doesn't regrow the smart_string a
4KB page at a time through its append loop. A small shared helper,
redis_zval_frame_est, returns an upper-bound RESP frame size per argument
(framing overhead plus the payload length when it's already a string;
non-strings get a fixed allowance). Each builder sums it over its args
in a cheap read-only pre-pass and reserves once.

Covers redis_key_varval_cmd (SADD/SREM/RPUSH/LPUSH/ZREM/...),
gen_key_arr_cmd (their array forms), gen_vararg_cmd, redis_mget_cmd, and
redis_hmset_cmd. The estimate only reads types and lengths, so it cannot
change the emitted bytes; under-estimating just falls back to growth.

gen_varkey_cmd (DEL/SUNION/SINTER/...) is left for a follow-up: its
single-array/timeout branching makes a clean reservation point less
obvious.

Verified on PHP 8.4: 1000-member SADD/RPUSH/sAddArray, 50KB-blob RPUSH,
800-key MGET, 400-field HMSET incl binary fields, prefix and PHP
serializer combinations; no leaks under report_memleaks; 25 project
suite methods pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant