summaryrefslogtreecommitdiff
path: root/src/server.c
diff options
context:
space:
mode:
authoruriyage <78144248+uriyage@users.noreply.github.com>2023-01-31 17:26:35 +0200
committerGitHub <noreply@github.com>2023-01-31 17:26:35 +0200
commit46393f9819ae29ddb86cb9819d0b055a923037b4 (patch)
tree6c140be408ea5fc7e77b5f402516a5e6ccec9294 /src/server.c
parente74a1f3bd995d3f298b6dfa134f085eacf63b1af (diff)
downloadredis-46393f9819ae29ddb86cb9819d0b055a923037b4.tar.gz
Optimization: sdsRemoveFreeSpace to avoid realloc on noop (#11766)
In #7875 (Redis 6.2), we changed the sds alloc to be the usable allocation size in order to: > reduce the need for realloc calls by making the sds implicitly take over the internal fragmentation This change was done most sds functions, excluding `sdsRemoveFreeSpace` and `sdsResize`, the reason is that in some places (e.g. clientsCronResizeQueryBuffer) we call sdsRemoveFreeSpace when we see excessive free space and want to trim it. so if we don't trim it exactly to size, the caller may still see excessive free space and call it again and again. However, this resulted in some excessive calls to realloc, even when there's no need and it's gonna be a no-op (e.g. when reducing 15 bytes allocation to 13). It turns out that a call for realloc with jemalloc can be expensive even if it ends up doing nothing, so this PR adds a check using `je_nallocx`, which is cheap to avoid the call for realloc. in addition to that this PR unifies sdsResize and sdsRemoveFreeSpace into common code. the difference between them was that sdsResize would avoid using SDS_TYPE_5, since it want to keep the string ready to be resized again, while sdsRemoveFreeSpace would permit using SDS_TYPE_5 and get an optimal memory consumption. now both methods take a `would_regrow` argument that makes it more explicit. the only actual impact of that is that in clientsCronResizeQueryBuffer we call both sdsResize and sdsRemoveFreeSpace for in different cases, and we now prevent the use of SDS_TYPE_5 in both. The new test that was added to cover this concern used to pass before this PR as well, this PR is just a performance optimization and cleanup. Benchmark: `redis-benchmark -c 100 -t set -d 512 -P 10 -n 100000000` on i7-9850H with jemalloc, shows improvement from 1021k ops/sec to 1067k (average of 3 runs). some 4.5% improvement. Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'src/server.c')
-rw-r--r--src/server.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/src/server.c b/src/server.c
index 8b4ec28e4..0d8d057bd 100644
--- a/src/server.c
+++ b/src/server.c
@@ -739,7 +739,7 @@ int clientsCronResizeQueryBuffer(client *c) {
/* There are two conditions to resize the query buffer: */
if (idletime > 2) {
/* 1) Query is idle for a long time. */
- c->querybuf = sdsRemoveFreeSpace(c->querybuf);
+ c->querybuf = sdsRemoveFreeSpace(c->querybuf, 1);
} else if (querybuf_size > PROTO_RESIZE_THRESHOLD && querybuf_size/2 > c->querybuf_peak) {
/* 2) Query buffer is too big for latest peak and is larger than
* resize threshold. Trim excess space but only up to a limit,
@@ -749,7 +749,7 @@ int clientsCronResizeQueryBuffer(client *c) {
size_t resize = sdslen(c->querybuf);
if (resize < c->querybuf_peak) resize = c->querybuf_peak;
if (c->bulklen != -1 && resize < (size_t)c->bulklen) resize = c->bulklen;
- c->querybuf = sdsResize(c->querybuf, resize);
+ c->querybuf = sdsResize(c->querybuf, resize, 1);
}
}