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. */
| 666 | * the previous one, when that happens, we wanna try to trim the unused space |
| 667 | * at the end of the last reply node which we won't use anymore. */ |
| 668 | void trimReplyUnusedTailSpace(client *c) { |
| 669 | listNode *ln = listLast(c->reply); |
| 670 | clientReplyBlock *tail = ln? (clientReplyBlock*)listNodeValue(ln): NULL; |
| 671 | |
| 672 | /* Note that 'tail' may be NULL even if we have a tail node, becuase when |
| 673 | * addReplyDeferredLen() is used */ |
| 674 | if (!tail) return; |
| 675 | |
| 676 | /* We only try to trim the space is relatively high (more than a 1/4 of the |
| 677 | * allocation), otherwise there's a high chance realloc will NOP. |
| 678 | * Also, to avoid large memmove which happens as part of realloc, we only do |
| 679 | * that if the used part is small. */ |
| 680 | if (tail->size - tail->used > tail->size / 4 && |
| 681 | tail->used < PROTO_REPLY_CHUNK_BYTES) |
| 682 | { |
| 683 | size_t old_size = tail->size; |
| 684 | tail = (clientReplyBlock*)zrealloc(tail, tail->used + sizeof(clientReplyBlock)); |
| 685 | /* take over the allocation's internal fragmentation (at least for |
| 686 | * memory usage tracking) */ |
| 687 | tail->size = zmalloc_usable_size(tail) - sizeof(clientReplyBlock); |
| 688 | c->reply_bytes = c->reply_bytes + tail->size - old_size; |
| 689 | listNodeValue(ln) = tail; |
| 690 | } |
| 691 | } |
| 692 | |
| 693 | /* Adds an empty object to the reply list that will contain the multi bulk |
| 694 | * length, which is not known when this function is called. */ |
no test coverage detected