diff options
author | Harkrishn Patro <harkrisp@amazon.com> | 2022-12-06 22:26:56 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-07 08:26:56 +0200 |
commit | c0267b3fa5808df475dec83c956b9a2bec112b90 (patch) | |
tree | fd3913a9b0d1fe8cbb08a0618ea719db886a9eb7 /src/networking.c | |
parent | 8a315fc285fc54c678b97107a02ee1627f2c1ebf (diff) | |
download | redis-c0267b3fa5808df475dec83c956b9a2bec112b90.tar.gz |
Optimize client memory usage tracking operation while client eviction is disabled (#11348)
## Issue
During the client input/output buffer processing, the memory usage is
incrementally updated to keep track of clients going beyond a certain
threshold `maxmemory-clients` to be evicted. However, this additional
tracking activity leads to unnecessary CPU cycles wasted when no
client-eviction is required. It is applicable in two cases.
* `maxmemory-clients` is set to `0` which equates to no client eviction
(applicable to all clients)
* `CLIENT NO-EVICT` flag is set to `ON` which equates to a particular
client not applicable for eviction.
## Solution
* Disable client memory usage tracking during the read/write flow when
`maxmemory-clients` is set to `0` or `client no-evict` is `on`.
The memory usage is tracked only during the `clientCron` i.e. it gets
periodically updated.
* Cleanup the clients from the memory usage bucket when client eviction
is disabled.
* When the maxmemory-clients config is enabled or disabled at runtime,
we immediately update the memory usage buckets for all clients (tested
scanning 80000 took some 20ms)
Benchmark shown that this can improve performance by about 5% in
certain situations.
Co-authored-by: Oran Agra <oran@redislabs.com>
Diffstat (limited to 'src/networking.c')
-rw-r--r-- | src/networking.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/src/networking.c b/src/networking.c index 76566ddd7..8e7c5ace1 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1970,7 +1970,7 @@ int writeToClient(client *c, int handler_installed) { * Since this isn't thread safe we do this conditionally. In case of threaded writes this is done in * handleClientsWithPendingWritesUsingThreads(). */ if (io_threads_op == IO_THREADS_OP_IDLE) - updateClientMemUsage(c); + updateClientMemUsageAndBucket(c); return C_OK; } @@ -2420,7 +2420,7 @@ int processCommandAndResetClient(client *c) { commandProcessed(c); /* Update the client's memory to include output buffer growth following the * processed command. */ - updateClientMemUsage(c); + updateClientMemUsageAndBucket(c); } if (server.current_client == NULL) deadclient = 1; @@ -2557,7 +2557,7 @@ int processInputBuffer(client *c) { * important in case the query buffer is big and wasn't drained during * the above loop (because of partially sent big commands). */ if (io_threads_op == IO_THREADS_OP_IDLE) - updateClientMemUsage(c); + updateClientMemUsageAndBucket(c); return C_OK; } @@ -2995,9 +2995,11 @@ NULL /* CLIENT NO-EVICT ON|OFF */ if (!strcasecmp(c->argv[2]->ptr,"on")) { c->flags |= CLIENT_NO_EVICT; + removeClientFromMemUsageBucket(c, 0); addReply(c,shared.ok); } else if (!strcasecmp(c->argv[2]->ptr,"off")) { c->flags &= ~CLIENT_NO_EVICT; + updateClientMemUsageAndBucket(c); addReply(c,shared.ok); } else { addReplyErrorObject(c,shared.syntaxerr); @@ -4228,7 +4230,7 @@ int handleClientsWithPendingWritesUsingThreads(void) { client *c = listNodeValue(ln); /* Update the client in the mem usage after we're done processing it in the io-threads */ - updateClientMemUsage(c); + updateClientMemUsageAndBucket(c); /* Install the write handler if there are pending writes in some * of the clients. */ @@ -4337,7 +4339,7 @@ int handleClientsWithPendingReadsUsingThreads(void) { } /* Once io-threads are idle we can update the client in the mem usage */ - updateClientMemUsage(c); + updateClientMemUsageAndBucket(c); if (processPendingCommandAndInputBuffer(c) == C_ERR) { /* If the client is no longer valid, we avoid @@ -4384,6 +4386,8 @@ size_t getClientEvictionLimit(void) { } void evictClients(void) { + if (!server.client_mem_usage_buckets) + return; /* Start eviction from topmost bucket (largest clients) */ int curr_bucket = CLIENT_MEM_USAGE_BUCKETS-1; listIter bucket_iter; |