-
Notifications
You must be signed in to change notification settings - Fork 556
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow a more efficient pattern of Pipeline memory allocation #176
Conversation
This change allows a performance sensitive tight loop to reuse a Pipeline object instead of allocating a new one each time. - `with_capacity` allows to preallocate the internal `commands` vector to the specified capacity. - `Pipeline.query_clear()` clears the internal `commands` vector from values after the query (but keeps the allocated capacity). - The unitests show the expected behaviour of `query` vs `query_clear`.
Thanks for the contribution! Just wanted to let you know that it will take a bit more until this gets looked at as I am on vacation. I plan to review it when I'm back in the third week of January. |
IMO the fact that we don't clear the internal command vector is a bug and we should just do that for query. That removes the need for any |
That will require |
Having |
@Marwes Why is that confusing behavior? What use-case do you think of to re-use the filled pipeline? |
Query then does more than just querying which makes it confusing if I don't care about reuse. If I am interested in clearing the pipeline for later reuse I am not going to expect that this is done automatically either so I will need to look up how to do that. A separate
A pipeline might be pre-created and used multiple for a commonly used query (incrementing/querying a global counter). Even disregarding that, changing the API to take |
I agree with @Marwes - that is why I created a new function. |
@badboy |
sorry for the silence for so long, this got a bit buried. I am fine with not changing |
fixes according to code review
@badboy |
[ci skip]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need slight rewording. The pipeline can be reused
regardless, it just differs on whether that is with the old commands or just re-using the (then cleared) allocation.
src/cmd.rs
Outdated
} | ||
|
||
/// Creates an empty pipeline with pre-allocated capacity. For consistency with the `cmd` | ||
/// api a `pipe` function is provided as alias. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second part here is not true. The pipe
function is only equivalent to new()
above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oopss. my bad. will fix.
src/cmd.rs
Outdated
@@ -480,6 +486,9 @@ impl Pipeline { | |||
/// .cmd("GET").arg("key_1") | |||
/// .cmd("GET").arg("key_2").query(&con).unwrap(); | |||
/// ``` | |||
/// | |||
/// NOTE: In order to clear (and reuse) the `Pipeline` object after calling `query()`, one must |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the reuse
here is slightly misleading.
Without clear the pipeline can be reused with the existing commands in it, clear
gives you a clean pipeline without losing the allocation.
Maybe something like:
NOTE: In order to clear and reuse an empty
Pipeline
object ...
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about:
NOTE: A
Pipeline
object may be reused afterquery()
with all the commands as were inserted to them. In order to clear aPipeline
object with minimal memory released/allocated, one should call theclear()
method before inserting new commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably "function" is better than "method".
src/cmd.rs
Outdated
@@ -493,6 +502,12 @@ impl Pipeline { | |||
) | |||
} | |||
|
|||
/// Clear the internal data strcture of `Pipeline`, allowing it to be reused. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here as before: make it more clear that it's empty afterwards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@badboy
Would you be kind enough to suggest a phrasing for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh... i see you did. didn't scroll up enough...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about:
Clear a
Pipeline
object internal data structure. This allows reusing aPipeline
object as a clear object but with a minimal amount of memory released/allocated.
src/cmd.rs
Outdated
@@ -554,6 +569,9 @@ impl Pipeline { | |||
/// # let con = client.get_connection().unwrap(); | |||
/// let _ : () = redis::pipe().cmd("PING").query(&con).unwrap(); | |||
/// ``` | |||
/// | |||
/// NOTE: In order to clear (and reuse) the `Pipeline` object after calling `execute()`, one | |||
/// must explicitly call `clear()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@badboy
as above... :)
@badboy |
I don't see any changes since my last review comments. |
@badboy |
[ci skip]
@badboy |
👍 |
@badboy |
I plan to have one more round of going through the open PRs and then cut a release, so probably tonight or tomorrow. |
* Add `LINSERT` command. (redis-rs#176) * Add `LINSERT` command. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * PR comments. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * changelog Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * PR comments. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * javadoc Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> --------- Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * Revert changelog. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * PR comments. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * Remove TODO. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * PR comments. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * PR comments + rename `Linsert` to `LInsert`. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * PR comments. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> * Fix UT. Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com> --------- Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com>
This change allows a performance sensitive tight loop to reuse a
Pipeline object instead of allocating a new one each time.
with_capacity
allows to preallocate the internalcommands
vectorto the specified capacity.
Pipeline.query_clear()
clears the internalcommands
vector fromvalues after the query (but keeps the allocated capacity).
query
vsquery_clear
.