summaryrefslogtreecommitdiff
path: root/src/networking.c
diff options
context:
space:
mode:
authorAriel Shtul <ariel.shtul@redislabs.com>2022-08-23 09:37:59 +0300
committerGitHub <noreply@github.com>2022-08-23 09:37:59 +0300
commit90223759a37d2613cd6f2085050f8ce2f9a54ee3 (patch)
treee45004cf640a37a2595e92d34c6193f7cf30f872 /src/networking.c
parent407b5c912f2a9151e760ed82515059d7bf6776f9 (diff)
downloadredis-90223759a37d2613cd6f2085050f8ce2f9a54ee3.tar.gz
[PERF] use snprintf once in addReplyDouble (#11093)
The previous implementation calls `snprintf` twice, the second time used to 'memcpy' the output of the first, which could be a very large string. The new implementation reserves space for the protocol header ahead of the formatted double, and then prepends the string length ahead of it. Measured improvement of simple ZADD of some 25%.
Diffstat (limited to 'src/networking.c')
-rw-r--r--src/networking.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/src/networking.c b/src/networking.c
index 6bf39d11a..d6471ee7c 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -840,13 +840,29 @@ void addReplyDouble(client *c, double d) {
d > 0 ? 6 : 7);
}
} else {
- char dbuf[MAX_LONG_DOUBLE_CHARS+3],
- sbuf[MAX_LONG_DOUBLE_CHARS+32];
- int dlen, slen;
+ char dbuf[MAX_LONG_DOUBLE_CHARS+32];
+ int dlen = 0;
if (c->resp == 2) {
- dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d);
- slen = snprintf(sbuf,sizeof(sbuf),"$%d\r\n%s\r\n",dlen,dbuf);
- addReplyProto(c,sbuf,slen);
+ /* In order to prepend the string length before the formatted number,
+ * but still avoid an extra memcpy of the whole number, we reserve space
+ * for maximum header `$0000\r\n`, print double, add the resp header in
+ * front of it, and then send the buffer with the right `start` offset. */
+ int dlen = snprintf(dbuf+7,sizeof(dbuf) - 7,"%.17g",d);
+ int digits = digits10(dlen);
+ int start = 4 - digits;
+ dbuf[start] = '$';
+
+ /* Convert `dlen` to string, putting it's digits after '$' and before the
+ * formatted double string. */
+ for(int i = digits, val = dlen; val && i > 0 ; --i, val /= 10) {
+ dbuf[start + i] = "0123456789"[val % 10];
+ }
+
+ dbuf[5] = '\r';
+ dbuf[6] = '\n';
+ dbuf[dlen+7] = '\r';
+ dbuf[dlen+8] = '\n';
+ addReplyProto(c,dbuf+start,dlen+9-start);
} else {
dlen = snprintf(dbuf,sizeof(dbuf),",%.17g\r\n",d);
addReplyProto(c,dbuf,dlen);