mirror of
https://github.com/redis/redis.git
synced 2026-02-03 20:39:54 -05:00
Avoid allocating and releasing list node in reply copy avoidance (#14739)
Some checks failed
CI / test-ubuntu-latest (push) Waiting to run
CI / test-sanitizer-address (push) Waiting to run
CI / build-debian-old (push) Waiting to run
CI / build-macos-latest (push) Waiting to run
CI / build-32bit (push) Waiting to run
CI / build-libc-malloc (push) Waiting to run
CI / build-centos-jemalloc (push) Waiting to run
CI / build-old-chain-jemalloc (push) Waiting to run
Codecov / code-coverage (push) Waiting to run
External Server Tests / test-external-standalone (push) Waiting to run
External Server Tests / test-external-cluster (push) Waiting to run
External Server Tests / test-external-nodebug (push) Waiting to run
Spellcheck / Spellcheck (push) Waiting to run
Reply-schemas linter / reply-schemas-linter (push) Has been cancelled
Some checks failed
CI / test-ubuntu-latest (push) Waiting to run
CI / test-sanitizer-address (push) Waiting to run
CI / build-debian-old (push) Waiting to run
CI / build-macos-latest (push) Waiting to run
CI / build-32bit (push) Waiting to run
CI / build-libc-malloc (push) Waiting to run
CI / build-centos-jemalloc (push) Waiting to run
CI / build-old-chain-jemalloc (push) Waiting to run
Codecov / code-coverage (push) Waiting to run
External Server Tests / test-external-standalone (push) Waiting to run
External Server Tests / test-external-cluster (push) Waiting to run
External Server Tests / test-external-nodebug (push) Waiting to run
Spellcheck / Spellcheck (push) Waiting to run
Reply-schemas linter / reply-schemas-linter (push) Has been cancelled
Optimizes handling of clients with referenced replies by embedding the `pending_ref_reply_node` list node in `client` and avoiding per-operation node alloc/free. there is an improvement: ~2% on 4 and 16 io-threads. ~1% on 8 io-threads
This commit is contained in:
parent
b209e8afde
commit
48aa1ce524
2 changed files with 15 additions and 8 deletions
|
|
@ -239,7 +239,7 @@ client *createClient(connection *conn) {
|
|||
c->auth_callback_privdata = NULL;
|
||||
c->auth_module = NULL;
|
||||
listInitNode(&c->clients_pending_write_node, c);
|
||||
c->pending_ref_reply_node = NULL;
|
||||
listInitNode(&c->pending_ref_reply_node, c);
|
||||
c->mem_usage_bucket = NULL;
|
||||
c->mem_usage_bucket_node = NULL;
|
||||
c->net_input_bytes_curr_cmd = 0;
|
||||
|
|
@ -519,6 +519,15 @@ void _addReplyToBufferOrList(client *c, const char *s, size_t len) {
|
|||
_addReplyPayloadToList(c, c->reply, s + reply_len, len - reply_len, PLAIN_REPLY);
|
||||
}
|
||||
|
||||
/* Check if the client's pending_ref_reply_node is currently linked in the list.
|
||||
* A node is considered linked if it has neighbors (prev/next), or if it's the
|
||||
* only node in the list (head points to it). */
|
||||
static inline int clientIsInPendingRefReplyList(client *c) {
|
||||
return listNextNode(&c->pending_ref_reply_node) != NULL ||
|
||||
listPrevNode(&c->pending_ref_reply_node) != NULL ||
|
||||
listFirst(server.clients_with_pending_ref_reply) == &c->pending_ref_reply_node;
|
||||
}
|
||||
|
||||
/* Increment reference to object and add pointer to object and
|
||||
* pointer to string itself to current reply buffer */
|
||||
static void _addBulkStrRefToBufferOrList(client *c, robj *obj, size_t len) {
|
||||
|
|
@ -549,9 +558,8 @@ static void _addBulkStrRefToBufferOrList(client *c, robj *obj, size_t len) {
|
|||
}
|
||||
|
||||
/* Track clients with pending referenced reply objects for async flushdb protection. */
|
||||
if (c->pending_ref_reply_node == NULL) {
|
||||
listAddNodeTail(server.clients_with_pending_ref_reply, c);
|
||||
c->pending_ref_reply_node = listLast(server.clients_with_pending_ref_reply);
|
||||
if (!clientIsInPendingRefReplyList(c)) {
|
||||
listLinkNodeTail(server.clients_with_pending_ref_reply, &c->pending_ref_reply_node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1903,9 +1911,8 @@ void unlinkClient(client *c) {
|
|||
* This should only be used when we are certain that the replies no longer
|
||||
* contain any referenced robj. */
|
||||
void tryUnlinkClientFromPendingRefReply(client *c, int force) {
|
||||
if (c->pending_ref_reply_node && (force || !clientHasPendingReplies(c))) {
|
||||
listDelNode(server.clients_with_pending_ref_reply, c->pending_ref_reply_node);
|
||||
c->pending_ref_reply_node = NULL;
|
||||
if (clientIsInPendingRefReplyList(c) && (force || !clientHasPendingReplies(c))) {
|
||||
listUnlinkNode(server.clients_with_pending_ref_reply, &c->pending_ref_reply_node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1577,7 +1577,7 @@ typedef struct client {
|
|||
/* list node in clients_pending_write list */
|
||||
listNode clients_pending_write_node;
|
||||
/* list node in clients_with_pending_ref_reply list */
|
||||
listNode *pending_ref_reply_node;
|
||||
listNode pending_ref_reply_node;
|
||||
/* Statistics and metrics */
|
||||
size_t net_input_bytes_curr_cmd; /* Total network input bytes read for the
|
||||
* execution of this client's current command. */
|
||||
|
|
|
|||
Loading…
Reference in a new issue