perf: Pre-size reply arrays where the element count is known

Several multibulk reply builders called array_init (8-bucket default)
right after reading the element count off the wire, forcing one or more
HashTable resizes as elements were appended. Switch these sites to
array_init_size using the known count.

The count is clamped to >= 0 because a null multibulk header yields -1,
and array_init_size takes a uint32_t; a negative value would otherwise
request a huge table. array_init_size(_, 0) is equivalent to array_init,
so the clamp is never worse than the prior behavior.

Covers redis_sock_read_multibulk_reply_zval, the LPOS COUNT path,
CLIENT TRACKINGINFO, HELLO, and nested multibulk in the recursive
variant reader.
This commit is contained in:
Ilia Alshanetsky
2026-06-02 18:10:20 -04:00
committed by Michael Grunder
parent 44f494428b
commit da514c71bb
+5 -5
View File
@@ -762,7 +762,7 @@ redis_sock_read_multibulk_reply_zval(RedisSock *redis_sock, zval *z_tab)
ZVAL_NULL(z_tab);
return NULL;
}
array_init(z_tab);
array_init_size(z_tab, numElems > 0 ? numElems : 0);
redis_mbulk_reply_loop(redis_sock, z_tab, numElems, UNSERIALIZE_ALL);
return z_tab;
@@ -1630,7 +1630,7 @@ redis_read_lpos_response(zval *zdst, RedisSock *redis_sock, char reply_type,
if (reply_type != TYPE_MULTIBULK)
return FAILURE;
array_init(zdst);
array_init_size(zdst, elements > 0 ? elements : 0);
for (i = 0; i < elements; ++i) {
if (redis_sock_gets(redis_sock, inbuf, sizeof(inbuf), &len) < 0) {
@@ -2060,7 +2060,7 @@ redis_client_trackinginfo_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
return FAILURE;
}
array_init(&z_ret);
array_init_size(&z_ret, numElems > 0 ? numElems : 0);
redis_read_multibulk_recursive(redis_sock, numElems, 0, &z_ret);
array_zip_values_and_scores(redis_sock, &z_ret, 0);
@@ -2100,7 +2100,7 @@ redis_hello_response(INTERNAL_FUNCTION_PARAMETERS,
if (read_mbulk_header(redis_sock, &numElems) < 0)
goto fail;
array_init(&z_ret);
array_init_size(&z_ret, numElems > 0 ? numElems : 0);
if (redis_read_multibulk_recursive(redis_sock, numElems, 0, &z_ret) != SUCCESS ||
array_zip_values_recursive(&z_ret) != SUCCESS)
@@ -4716,7 +4716,7 @@ redis_read_multibulk_recursive(RedisSock *redis_sock, long long elements, int st
if (reply_info < 0 && redis_sock->null_mbulk_as_null) {
add_next_index_null(z_ret);
} else {
array_init(&z_subelem);
array_init_size(&z_subelem, reply_info > 0 ? reply_info : 0);
if (reply_info > 0) {
redis_read_multibulk_recursive(redis_sock, reply_info, status_strings, &z_subelem);
}