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. */
| 535 | * the previous one, when that happens, we wanna try to trim the unused space |
| 536 | * at the end of the last reply node which we won't use anymore. */ |
| 537 | void trimReplyUnusedTailSpace(client *c) { |
| 538 | listNode *ln = listLast(c->reply); |
| 539 | clientReplyBlock *tail = ln? listNodeValue(ln): NULL; |
| 540 | |
| 541 | /* Note that 'tail' may be NULL even if we have a tail node, because when |
| 542 | * addReplyDeferredLen() is used */ |
| 543 | if (!tail) return; |
| 544 | |
| 545 | /* We only try to trim the space is relatively high (more than a 1/4 of the |
| 546 | * allocation), otherwise there's a high chance realloc will NOP. |
| 547 | * Also, to avoid large memmove which happens as part of realloc, we only do |
| 548 | * that if the used part is small. */ |
| 549 | if (tail->size - tail->used > tail->size / 4 && |
| 550 | tail->used < PROTO_REPLY_CHUNK_BYTES) |
| 551 | { |
| 552 | size_t old_size = tail->size; |
| 553 | tail = zrealloc(tail, tail->used + sizeof(clientReplyBlock)); |
| 554 | /* take over the allocation's internal fragmentation (at least for |
| 555 | * memory usage tracking) */ |
| 556 | tail->size = zmalloc_usable_size(tail) - sizeof(clientReplyBlock); |
| 557 | c->reply_bytes = c->reply_bytes + tail->size - old_size; |
| 558 | listNodeValue(ln) = tail; |
| 559 | } |
| 560 | } |
| 561 | |
| 562 | /* Adds an empty object to the reply list that will contain the multi bulk |
| 563 | * length, which is not known when this function is called. */ |
no test coverage detected