Skip to content

Shared reusable client for RM_Call()#8516

Merged
oranagra merged 3 commits intoredis:unstablefrom
zuiderkwast:reusable-module-client
Feb 28, 2021
Merged

Shared reusable client for RM_Call()#8516
oranagra merged 3 commits intoredis:unstablefrom
zuiderkwast:reusable-module-client

Conversation

@zuiderkwast
Copy link
Contributor

A single client pointer is added in the server struct. This is
initialized by the first RM_Call() and reused for every subsequent
RM_Call() except if it's already in use, which means that it's not
used for (recursive) module calls to modules. For these, a new
"fake" client is created each time.

A single client pointer is added in the server struct. This is
initialized by the first RM_Call() and reused for every subsequent
RM_Call() except if it's already in use, which means that it's not
used for (recursive) module calls to modules. For these, a new
"fake" client is created each time.
@zuiderkwast
Copy link
Contributor Author

This is a follow-up on #4623, based on the latest comments.

Is something more from the resetCommand needed? I suspect these could be needed:

discardTransaction(c);
pubsubUnsubscribeAllChannels(c,0);
pubsubUnsubscribeAllPatterns(c,0);

@oranagra
Copy link
Member

We certainly need discardTransaction(c) maybe other parts of reset too, just need to make sure they don't have any side effect of causing slowness when there's nothing to reset (e.g. Nothing to unsubscribe) .

I was thinking about making the server struct member a stack (list) so that repeated calls to RM_Call enjoy some re-use, but then a single nested call would still create a new client, so maybe we better look into why these allocations are so expensive instead.

@zuiderkwast
Copy link
Contributor Author

Last commits add all the necessary reset steps. They are no-ops in the normal case. I've compared with what resetCommand and freeClient are doing.

I was thinking about making the server struct member a stack (list)

This PR adds the most simple optimization with a single client. I think module-call-module is a corner case already.

If it's actually common enough that it needs to be optimized, we could also use small fixed size array of clients (e.g. 3 or 4 clients), where each RM_Call can loop over them to find one which is free to use (it's free if argv == NULL). No need to allocate the list nodes in that case.

@yossigo
Copy link
Collaborator

yossigo commented Feb 21, 2021

I think this is a great improvement as it is.

@oranagra oranagra added the release-notes indication that this issue needs to be mentioned in the release notes label Feb 28, 2021
@oranagra oranagra merged commit 6122f1c into redis:unstable Feb 28, 2021
This was referenced Feb 28, 2021
JackieXie168 pushed a commit to JackieXie168/redis that referenced this pull request Mar 2, 2021
A single client pointer is added in the server struct. This is
initialized by the first RM_Call() and reused for every subsequent
RM_Call() except if it's already in use, which means that it's not
used for (recursive) module calls to modules. For these, a new
"fake" client is created each time.

Other changes:
* Avoid allocating a dict iterator in pubsubUnsubscribeAllChannels
  when not needed
@zuiderkwast zuiderkwast mentioned this pull request Sep 14, 2021
52 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-notes indication that this issue needs to be mentioned in the release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants