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

Is there a way to avoid heap allocating for every message sent/received? #172

Closed
jgarvin opened this issue Jan 31, 2021 · 5 comments
Closed
Labels

Comments

@jgarvin
Copy link

jgarvin commented Jan 31, 2021

In the example read_message and write_message deal with the Message type, which contains a bunch of owning types (either String or Vec<u8>) rather than references. AFAICT this means you can't just reuse the same buffer in place over and over, and have to make fresh allocations every message. Is there a way around this?

@agalakhov
Copy link
Member

I had this idea but did not implement it due to minor performance impact on modern allocators. They handle this situation (freeing and then reallocating) quite well. Reusing buffers makes ownership handling more difficult since you can't receive anything until previous message is processed and you can't just keep incoming messages in memory. Choosing between simpler API and potentially slightly better performance I choose the API.

Could you measure or estimate the performance impact? Is it really worth implementing?

@jgarvin
Copy link
Author

jgarvin commented Feb 1, 2021

I suspect you wouldn't hit the happy path in allocators because your allocation size is going to vary based on message length. Whether the performance hit is significant is going to depend on what the application requires, allocator implementation and the pattern of allocations between messages. Any allocation can trigger system calls to request more memory from the OS which can be expensive for some applications. What I can say for sure is that if you support an API that doesn't allocate, you can always build a more convenient API that does allocate on top of it, but you can't do it the other way around.

You could maybe minimize the API pain by having Message (contains references) that impls Into<OwningMessage>. That still makes it fairly straightforward to store messages if that's what users want to do. Another overhead users could avoid here would be if Text messages were still u8 slices instead of str or String, and let users opt-in to the conversion (which may not be necessary for say a blind message forwarding process).

@aldanor
Copy link

aldanor commented Feb 11, 2021

you can't receive anything until previous message is processed and you can't just keep incoming messages in memory

Unless some sort of arena allocator is used internally?

@vorner
Copy link

vorner commented Mar 12, 2021

I wonder if the way forward would be to use the Bytes. One can chunk off multiple of them from one BytesMut and if they are freed soon enough, they just return back into the original BytesMut (on call to reserve). But they can also be passed on to the sending end. And even prost is going to support zero-copy parsing from Bytes.

The Text one can use some kind of wrapper, like this one.

@daniel-abramov
Copy link
Member

It seems like the original questions have been answered, so I'm going to close the issue.

Feel free to open a new one or re-open the existing one if you plan to turn it into feature / work on a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants