Skip to content
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

Merged
merged 4 commits into from
Feb 17, 2019

Conversation

tsnoam
Copy link
Contributor

@tsnoam tsnoam commented Dec 30, 2018

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.

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`.
@badboy
Copy link
Collaborator

badboy commented Jan 5, 2019

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.

@badboy badboy self-requested a review January 5, 2019 19:24
@badboy
Copy link
Collaborator

badboy commented Jan 15, 2019

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 query_clear function.

@badboy
Copy link
Collaborator

badboy commented Jan 15, 2019

That will require &mut self on query and execute on Pipeline, but I think it's worthwhile (but should also be documented clearly)

@Marwes
Copy link
Collaborator

Marwes commented Jan 15, 2019

Having query clear the pipeline seems like really confusing behaviour to me. Just having a separate clear method on the pipeline seems more straightforward.

@badboy
Copy link
Collaborator

badboy commented Jan 15, 2019

@Marwes Why is that confusing behavior? What use-case do you think of to re-use the filled pipeline?

@Marwes
Copy link
Collaborator

Marwes commented Jan 16, 2019

Why is that confusing behavior?

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 clear method would be more discoverable in that case.

What use-case do you think of to re-use the filled pipeline?

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 &mut would prevent usage when only a & is available (which does not necessarily mean that the pipeline is used more than once, it might just be a part of a another object that is shared).

@tsnoam
Copy link
Contributor Author

tsnoam commented Jan 16, 2019

I agree with @Marwes - that is why I created a new function.
I'm also ok with having an explicit clear() function instead of query_clear(). However, I think that most user would want the combined method, so for better ergonomics, I'd prefer to keep query_clear().

@tsnoam
Copy link
Contributor Author

tsnoam commented Jan 17, 2019

@badboy
I'd be happy to change my PR according to your decision. So what would it be?

@badboy
Copy link
Collaborator

badboy commented Jan 23, 2019

sorry for the silence for so long, this got a bit buried.

I am fine with not changing query, but introducing a clear method instead. In addition documenting that query doesn't clear would be needed.

@tsnoam
Copy link
Contributor Author

tsnoam commented Jan 24, 2019

@badboy
I've changed the code as requested.

Copy link
Collaborator

@badboy badboy left a 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.
Copy link
Collaborator

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.

Copy link
Contributor Author

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
Copy link
Collaborator

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?

Copy link
Contributor Author

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 after query() with all the commands as were inserted to them. In order to clear a Pipeline object with minimal memory released/allocated, one should call the clear()method before inserting new commands.

Copy link
Contributor Author

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.
Copy link
Collaborator

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.

Copy link
Contributor Author

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?

Copy link
Contributor Author

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...

Copy link
Contributor Author

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 a Pipeline 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()`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@badboy
as above... :)

@tsnoam
Copy link
Contributor Author

tsnoam commented Jan 24, 2019

@badboy
Please see my comments on the review.

@badboy
Copy link
Collaborator

badboy commented Jan 25, 2019

I don't see any changes since my last review comments.
Did you push?

@tsnoam
Copy link
Contributor Author

tsnoam commented Jan 25, 2019

@badboy
I replied on your comments (started a discussion), please take a look there.

@tsnoam
Copy link
Contributor Author

tsnoam commented Feb 1, 2019

@badboy
I've pushed a commit with the documentation changes as I suggested them on the comments.
I hope you'll find it appropriate.

@badboy badboy mentioned this pull request Feb 5, 2019
@badboy badboy merged commit dd00e78 into redis-rs:master Feb 17, 2019
@badboy
Copy link
Collaborator

badboy commented Feb 17, 2019

👍

@tsnoam
Copy link
Contributor Author

tsnoam commented Feb 18, 2019

@badboy
Not to be blunt or anything, but when would it be possible to push a new release (with this merged PR) to crates.io?

@badboy
Copy link
Collaborator

badboy commented Feb 18, 2019

I plan to have one more round of going through the open PRs and then cut a release, so probably tonight or tomorrow.

barshaul pushed a commit to barshaul/redis-rs that referenced this pull request Jul 11, 2024
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants