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

Document that Builders cannot be re-used? #111

Open
FrancisRussell opened this issue Nov 7, 2018 · 5 comments
Open

Document that Builders cannot be re-used? #111

FrancisRussell opened this issue Nov 7, 2018 · 5 comments

Comments

@FrancisRussell
Copy link

FrancisRussell commented Nov 7, 2018

From the documentation, it's unclear if Builders can be re-used. The presence of init_root() gives the impression that a Builder can be re-initialized for construction of a new message. Given that one wishes to avoid repeated memory allocations, this seems like an obvious thing to do, but attempting to do so results in increasingly larger messages (presumably all the previous messages concatenated, but I've not checked this in depth).

@dwrensha
Copy link
Member

dwrensha commented Nov 8, 2018

Yep, the init_ methods clear out the old data, but don't reclaim the old space. More documentation about this would be good.

@FrancisRussell
Copy link
Author

Does this mean, as appeared to be the case, that a Builder cannot be re-used? If so, is this behaviour deliberate?

@dwrensha
Copy link
Member

dwrensha commented Nov 8, 2018

You can reuse a message::Builder, but the usefulness of doing so is limited because you will continue to accumulate unused memory that can only be reclaimed by dropping the message::Builder.

The best way to avoid allocations between messages is to use message::ScratchSpaceHeapAllocator. That allows you to specify a buffer that will be used for the first segment of your message and can be reused between messages.

@tv42
Copy link

tv42 commented Dec 29, 2023

You can get rid of the old values by canonicalizing the message.

let reader = builder.get_root_as_reader()?;
let mut compacted_builder = capnp::message::Builder::new_default();
compacted_builder.set_root_canonical(reader)?;
capnp::serialize::write_message(&mut buf, &compacted_builder)?;

This probably won't make sense performance-wise for many scenarios, but I figured it out to learn how to update a message without needing to copy old message contents field by field (that would be a maintenance burden, easy to forget to change as schema changes).

@dwrensha
Copy link
Member

Just plain compacted_builder.set_root() works too, and won't fail if the message needs more than one segment.

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

No branches or pull requests

3 participants