-
Notifications
You must be signed in to change notification settings - Fork 585
Implement Arc, Box wrapper of message fields.
#705
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
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. |
caspermeijn
left a comment
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.
| 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?
|
|
||
| // TODO: Merge `boxed` with `field_wrapper` | ||
| 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) 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).
| 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)