mirror of
https://github.com/phpredis/phpredis.git
synced 2026-06-19 07:35:31 +00:00
perf: Avoid per-key heap allocation in ra_find_node hash path
When a RedisArray uses a custom hash algorithm, ra_find_node allocated the hash context and digest buffers on the heap for every key lookup. Both are small (the largest common context is SHA-512 at ~208 bytes), so use stack buffers for the common case and fall back to emalloc only when an algorithm's context or digest exceeds them. The context buffer is a union with a double member to guarantee the alignment the context structs require for their uint64_t state.
This commit is contained in:
committed by
Michael Grunder
parent
da514c71bb
commit
8b746bfc78
+11
-4
@@ -497,8 +497,15 @@ ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos)
|
||||
|
||||
/* hash */
|
||||
if (ra->algorithm && (ops = redis_hash_fetch_ops(ra->algorithm))) {
|
||||
void *ctx = emalloc(ops->context_size);
|
||||
unsigned char *digest = emalloc(ops->digest_size);
|
||||
/* The union forces alignment suitable for any hash context
|
||||
* struct (they hold uint64_t state); fall back to the heap for
|
||||
* the rare algorithm whose context/digest exceeds the buffer. */
|
||||
union { double align; unsigned char buf[256]; } ctx_stack;
|
||||
unsigned char digest_stack[64];
|
||||
void *ctx = ops->context_size <= sizeof(ctx_stack) ? (void *)&ctx_stack
|
||||
: emalloc(ops->context_size);
|
||||
unsigned char *digest = ops->digest_size <= sizeof(digest_stack) ? digest_stack
|
||||
: emalloc(ops->digest_size);
|
||||
|
||||
#if PHP_VERSION_ID >= 80100
|
||||
ops->hash_init(ctx,NULL);
|
||||
@@ -511,8 +518,8 @@ ra_find_node(RedisArray *ra, const char *key, int key_len, int *out_pos)
|
||||
memcpy(&ret, digest, MIN(sizeof(ret), ops->digest_size));
|
||||
ret %= 0xffffffff;
|
||||
|
||||
efree(digest);
|
||||
efree(ctx);
|
||||
if (digest != digest_stack) efree(digest);
|
||||
if (ctx != (void *)&ctx_stack) efree(ctx);
|
||||
} else {
|
||||
for (i = 0; i < ZSTR_LEN(out); ++i) {
|
||||
CRC32(ret, ZSTR_VAL(out)[i]);
|
||||
|
||||
Reference in New Issue
Block a user