Unverified Commit 5725088f authored by yoav-steinberg's avatar yoav-steinberg Committed by GitHub
Browse files

Avoid argv memcpy when queuing a multi command. (#9602)

When queuing a multi command we duplicated the argv (meaning an alloc
and a memcpy). This isn't needed since we can use the previously allocated
argv and just reset the client objects argv to NULL. This should saves some
memory and is a minor optimization in heavy MULTI/EXEC traffic, especially
if there are lots of arguments.
parent 4fb39b67
...@@ -58,7 +58,6 @@ void freeClientMultiState(client *c) { ...@@ -58,7 +58,6 @@ void freeClientMultiState(client *c) {
/* Add a new command into the MULTI commands queue */ /* Add a new command into the MULTI commands queue */
void queueMultiCommand(client *c) { void queueMultiCommand(client *c) {
multiCmd *mc; multiCmd *mc;
int j;
/* No sense to waste memory if the transaction is already aborted. /* No sense to waste memory if the transaction is already aborted.
* this is useful in case client sends these in a pipeline, or doesn't * this is useful in case client sends these in a pipeline, or doesn't
...@@ -72,14 +71,20 @@ void queueMultiCommand(client *c) { ...@@ -72,14 +71,20 @@ void queueMultiCommand(client *c) {
mc = c->mstate.commands+c->mstate.count; mc = c->mstate.commands+c->mstate.count;
mc->cmd = c->cmd; mc->cmd = c->cmd;
mc->argc = c->argc; mc->argc = c->argc;
mc->argv = zmalloc(sizeof(robj*)*c->argc); mc->argv = c->argv;
memcpy(mc->argv,c->argv,sizeof(robj*)*c->argc); mc->argv_len = c->argv_len;
for (j = 0; j < c->argc; j++)
incrRefCount(mc->argv[j]);
c->mstate.count++; c->mstate.count++;
c->mstate.cmd_flags |= c->cmd->flags; c->mstate.cmd_flags |= c->cmd->flags;
c->mstate.cmd_inv_flags |= ~c->cmd->flags; c->mstate.cmd_inv_flags |= ~c->cmd->flags;
c->mstate.argv_len_sums += c->argv_len_sum + sizeof(robj*)*c->argc; c->mstate.argv_len_sums += c->argv_len_sum + sizeof(robj*)*c->argc;
/* Reset the client's args since we copied them into the mstate and shouldn't
* reference them from c anymore. */
c->argv = NULL;
c->argc = 0;
c->argv_len_sum = 0;
c->argv_len = 0;
} }
void discardTransaction(client *c) { void discardTransaction(client *c) {
...@@ -206,8 +211,9 @@ void execCommand(client *c) { ...@@ -206,8 +211,9 @@ void execCommand(client *c) {
orig_cmd = c->cmd; orig_cmd = c->cmd;
addReplyArrayLen(c,c->mstate.count); addReplyArrayLen(c,c->mstate.count);
for (j = 0; j < c->mstate.count; j++) { for (j = 0; j < c->mstate.count; j++) {
c->argv_len = c->argc = c->mstate.commands[j].argc; c->argc = c->mstate.commands[j].argc;
c->argv = c->mstate.commands[j].argv; c->argv = c->mstate.commands[j].argv;
c->argv_len = c->mstate.commands[j].argv_len;
c->cmd = c->mstate.commands[j].cmd; c->cmd = c->mstate.commands[j].cmd;
/* ACL permissions are also checked at the time of execution in case /* ACL permissions are also checked at the time of execution in case
......
...@@ -790,6 +790,7 @@ typedef struct dbBackup dbBackup; ...@@ -790,6 +790,7 @@ typedef struct dbBackup dbBackup;
/* Client MULTI/EXEC state */ /* Client MULTI/EXEC state */
typedef struct multiCmd { typedef struct multiCmd {
robj **argv; robj **argv;
int argv_len;
int argc; int argc;
struct redisCommand *cmd; struct redisCommand *cmd;
} multiCmd; } multiCmd;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment