diff options
author | Salvatore Sanfilippo <antirez@gmail.com> | 2020-05-04 10:20:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-04 10:20:31 +0200 |
commit | b3f3d5a42fec96bb062feb2cc6f5e79d7039b874 (patch) | |
tree | 1945a66f276a9877528b15202f2489803a6663e3 | |
parent | 57697373efcc5189d67d53955f1df609ebbb9a8d (diff) | |
parent | 6726b3c2cb41e700c8cfd2f821df6c8c847a5ddc (diff) | |
download | redis-b3f3d5a42fec96bb062feb2cc6f5e79d7039b874.tar.gz |
Merge pull request #7176 from oranagra/fix-optimize-reply-buffer
optimize memory usage of deferred replies - fixed
-rw-r--r-- | src/networking.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/networking.c b/src/networking.c index c4a277e0a..d62533e3e 100644 --- a/src/networking.c +++ b/src/networking.c @@ -436,6 +436,34 @@ void addReplyStatusFormat(client *c, const char *fmt, ...) { sdsfree(s); } +/* Sometimes we are forced to create a new reply node, and we can't append to + * the previous one, when that happens, we wanna try to trim the unused space + * at the end of the last reply node which we won't use anymore. */ +void trimReplyUnusedTailSpace(client *c) { + listNode *ln = listLast(c->reply); + clientReplyBlock *tail = ln? listNodeValue(ln): NULL; + + /* Note that 'tail' may be NULL even if we have a tail node, becuase when + * addDeferredMultiBulkLength() is used */ + if (!tail) return; + + /* We only try to trim the space is relatively high (more than a 1/4 of the + * allocation), otherwise there's a high chance realloc will NOP. + * Also, to avoid large memmove which happens as part of realloc, we only do + * that if the used part is small. */ + if (tail->size - tail->used > tail->size / 4 && + tail->used < PROTO_REPLY_CHUNK_BYTES) + { + size_t old_size = tail->size; + tail = zrealloc(tail, tail->used + sizeof(clientReplyBlock)); + /* take over the allocation's internal fragmentation (at least for + * memory usage tracking) */ + tail->size = zmalloc_usable(tail) - sizeof(clientReplyBlock); + c->reply_bytes += tail->size - old_size; + listNodeValue(ln) = tail; + } +} + /* Adds an empty object to the reply list that will contain the multi bulk * length, which is not known when this function is called. */ void *addReplyDeferredLen(client *c) { @@ -443,6 +471,7 @@ void *addReplyDeferredLen(client *c) { * ready to be sent, since we are sure that before returning to the * event loop setDeferredAggregateLen() will be called. */ if (prepareClientToWrite(c) != C_OK) return NULL; + trimReplyUnusedTailSpace(c); listAddNodeTail(c->reply,NULL); /* NULL is our placeholder. */ return listLast(c->reply); } |