-
Notifications
You must be signed in to change notification settings - Fork 507
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
Implement Arc
, Box
wrapper of message fields.
#705
base: master
Are you sure you want to change the base?
Conversation
Arc
, Rc
, Box
wrapper of message fields.Arc
, Box
wrapper of message fields.
255b101
to
154c338
Compare
Mostly done, add more tests later. |
Nice! Just want to let you know I see this but I have a bunch of high priority things on my plate atm so may take me a bit to get to a review of this. |
064005a
to
6547129
Compare
How is this working out? It's sad that I have to call many Vec::clone() to send a message with repeated fields to thousands of clients 😥. I'm hoping this PR will solve my problem. |
I just want to second this. Having Arc would be sweet, as memory consumption on some structs is reaching relative high levels in quickwit |
Any updates on this? |
Yes, this PR needs a reviewer and someone to bring it to the finish line. @Remediem Are you willing to do some of that work? |
@juanAngel When I said, “this PR needs a reviewer”, I didn't mean someone who hits the Approve button. I meant someone who provides useful comments about the large code changes. Maybe you are willing to split this PR is multiple smaller PRs that are easier to review? |
This PR is ready for review at 2022. The I can't split it into smaller PRs as it's quite self-contained, and most of the new code is from the tests. @caspermeijn @LucioFranco Could you review the test code in this PR and let me know if it's acceptable? If you are still interested in the |
Don't think I didn't read the code before hitting the button And I was implementing those improvements on my own. As for the rest I don't know what kind of comments are needed if the code/tests seem to be correct |
@juanAngel I'm sorry I reacted that way. There have been some low effort comments lately and I confused your approval with that. Thank you for explaining what you have reviewed, and thank you for the review. |
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.
Arc
is a much requested feature. Thank you for implementing it.
I like the concept of a wrapper type. I like that it is mutual exclusive, as that reduces the possible combinations. I like that it only contains allocating wrappers.
The diff will be smaller after merging this code path with the existing boxed
code.
Please add user-facing documentation.
@@ -421,6 +444,35 @@ impl Config { | |||
self | |||
} | |||
|
|||
fn field_wrapper<I, S>(&mut self, paths: I, wrapper: Wrapper) |
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.
Thinking out loud: Is it beneficial to make field_wrapper
public instead of arc
and box
? That way, it is clear that they are mutual exclusive.
let field_wrapper = self | ||
.config | ||
.field_wrappers | ||
.get_first_field(fq_message_name, oneof.name()) |
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.
Do we want to error out if there are conflicting field wrappers defined for a single field?
let boxed = !repeated | ||
&& field_wrapper != Some(Wrapper::Box) |
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 message graph boxed detection is for solving recursive types. If a recursive type is detected, then it is automatically placed in a Box to make sure the struct size is known at compile time. Arc
will have the same function.
I don't think message graph will take the explicit boxed into account. Maybe it should with more field wrappers?
pub(crate) struct PathMap<T> { | ||
// insertion order might actually matter (to avoid warning about legacy-derive-helpers) | ||
// see: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#legacy-derive-helpers | ||
pub(crate) matchers: Vec<(String, T)>, | ||
} | ||
|
||
// Remove this after <https://github.com/rust-lang/rust/issues/26925> is fixed. |
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.
Interesting that this trigger without changing the struct. I would like to see a comment to explain why this is needed (without reading the GitHub issue).
@@ -25,6 +29,8 @@ impl Field { | |||
set_bool(&mut group, "duplicate group attributes")?; | |||
} else if word_attr("boxed", attr) { | |||
set_bool(&mut boxed, "duplicate boxed attributes")?; | |||
} else if let Some(w) = wrapper_attr(attr) { |
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 boxed
code path should be merged into the wrapper code path.
match wrapper { | ||
Some(Wrapper::Arc) => { | ||
quote!(::prost::alloc::sync::Arc::get_mut(&mut self.#ident).ok_or_else(|| { | ||
::prost::DecodeError::new("Cannot get mutable reference to a Arc field") |
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.
When can this happen? During decoding, there will never be another Arc
to the same allocation, right? Is make_mut
useful here?
pub(super) fn tag_attr(attr: &Meta) -> Result<Option<u32>, Error> { | ||
// TODO pub(crate)? | ||
#[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
pub enum Wrapper { |
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.
Should the Wrapper
type and helper functions be in a separate module to reduce file size?
/// Get reference of a field. | ||
fn field_ref(wrapper: &Option<Wrapper>, ident: TokenStream) -> TokenStream { | ||
if wrapper.is_some() { | ||
quote!(&*#ident) |
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 feel like the *
could make a copy of the contents. Maybe as_ref()
can help here. Would it be possible to replace field_ref
by as_ref
?
let pushed = wrapper.wrap_type(quote!(pushed)); | ||
quote! { | ||
let mut pushed = (*#field).clone(); | ||
pushed.push(value as i32); | ||
self.#ident = #pushed; | ||
} |
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.
Can you explain why this is needed?
@@ -0,0 +1,10 @@ | |||
[package] | |||
name = "field-wrappers" |
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 would like the tests to be part of crate tests
as that crate is run for every edition and with no-std
.
} | ||
|
||
self.buf.push_str("::core::option::Option<"); | ||
self.buf.push_str(&name); |
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.
Wouldn't it be better if arc was inside the option?
Normally you will try to clone the content of the option, not the whole option. And cloning a some or none I don't think will be a big cost.
self.buf.push_str("=\""); | ||
self.buf.push_str(&key_tag); | ||
self.buf.push_str(", "); | ||
self.buf.push_str(&value_tag); |
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.
Here it might be interesting to add an extra arc/box just for the value
That way you can share the individual elements
For the key, from my point of view it is less necessary since they are usually easily copied elements and are mostly only used for searches or insertions
.config | ||
.field_wrappers | ||
.get_first_field(fq_message_name, field.name()) | ||
.copied(); |
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.
In my opinion it is interesting to add a filter here.
Since you will never want an enum wrapped in arc, or an integer
Since they are much cheaper to clone than arc itself, in addition to implementing automatic copying
Is there any progress on this issue? When is it expected to be merged? thanks. |
@nothing2sayi Yeah, I am working on this. I have successfully rebased this MR locally. But there are several bugs in the current implementation of |
Closes #429
Marked as draft since tests haven't been added.(Go to bed now :-P)