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

Alternative interface for bytes_vectored #334

Open
Kixunil opened this issue Nov 28, 2019 · 1 comment
Open

Alternative interface for bytes_vectored #334

Kixunil opened this issue Nov 28, 2019 · 1 comment

Comments

@Kixunil
Copy link

Kixunil commented Nov 28, 2019

Currently, bytes_vectored takes a slice of initialized IoSliceMut. This has two drawbacks:

  • If one wants to be pretty sure that the slice will have sufficient length, he may want to allocate e.g. 128 items-long array on stack and pass it in, however, he needs to initialize each item, causing slow down.
  • bytes_vectored is tied to specific implementation of vectored slice from std this makes it clunky to work in no_std (one has to conditionally implement the method) and could miss potential opportunities. If there's any no_std library that would like to use vectored API, it's impossible to do. If there's some exotic platform that needs different io slices for different calls, only one can be optimized. (Unlikely, but still...)

The way to solve both problems is to pass in some kind of trait that can take normal Rust slice and convert it internally into whatever is needed. There are different options of how to do that:

  • simple FnMut: fn bytes_vectored<'a, F: FnMut(&'a mut [MaybeUninit<u8>])>(&'a mut self, pusher: F);
  • FnMut with MaybeUninitSlice<u8>: fn bytes_vectored<'a, F: FnMut(&'a mut MaybeUninitSlice<u8>)>(&'a mut self, pusher: F); - this seems the most simple to me
  • A custom trait instead of FnMut with fn push_init(&mut self, data: &mut [u8]) and fn push_uninit(&mut [MaybeUninit<u8>])

Of course, this brings the question what about dyn traits. I'm not really sure how often dyn is used in this context. One possibility is to provide fn bytes_vectored_dyn too. Another would be to provide some helper bridging trait for that, but that's becoming complicated.

Alternatively, it could be decided that conversion to native slice is not needed and use something like possibly_uninit::slice::Cursor<IoSliceMut>.

Another possibility would be to make BufMut trait generic over io slice item type, requiring implementation of From<&mut [u8]> and From<&mut [MaybeUninit<u8>]> and ideally also From<&mut MaybeUninitSlice<u8>>, but until we have HRTB for types in Rust, it might be less useful.

I gave examples on BytesMut trait, which is more complicated, but the same goes for Bytes trait.

@Kixunil
Copy link
Author

Kixunil commented Nov 29, 2019

I just realized my proposal also solves the problem raised in tokio-rs/tokio#1744 (comment) regarding many small slices passed to something that doesn't support vectored IO. If the writer doesn't support vectored IO, it can simply pass a closure that copies the data between staging buffer and the slices instead.

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

1 participant