Open colinmarc opened 9 months ago
Thanks for the questions / proposal.
We've talked in the past about optimizing the send path for datagrams, primarily around reducing copies. The idea was loosely to use traits and pass those in rather than the actual data, then can the framing and packetization can happen later during quiche's regular send().
The suggestion to support a more immediate mode of packet creation is interesting. But it adds yet another thing for apps to have to worry about. In addition it also complicates the model we have around congestion control and packet pacing. That's not something retry or version negotiation need to care about. Reducing the efficacy of the congestion controller can undo any perf enhancements that reducing copies might achieve.
The trait approach aligns with our current model and is probably minor API change. Maybe your interested in trying that out?
Hi, thanks for the quick response!
For the trait, would Deref<Target=[u8]>
be right? That would support Bytes
and smart pointers like Arc<[u8]>
, as well as Vec
. That would only eliminate one of the copies, but that's better than nothing.
I'm working on an application that sends lots and lots of datagrams (for video), and it strikes me that the current API for datagrams is not very flexible or optimized. This seems to be a result of integrating the datagram functionality into the normal
send
path, despite datagrams not needing to be interleaved with stream packets at all, per my lackluster understanding of QUIC.In the worst case, I have a
Bytes
with some data I want to send. I calldgram_send(&buf)
. The packet first gets copied into the queue here:https://github.com/cloudflare/quiche/blob/883a616f0bf3258f1898e0fad0c3707c630f81b0/quiche/src/lib.rs#L5347
(Note that there's a
dgram_send_vec
which doesn't copy, but it's pretty tricky to have aVec
at that point.)Then, when I call
send
, I have no control over whether the datagrams are prioritized. If they are picked out of the queue, there's another copy into the packet buffer:https://github.com/cloudflare/quiche/blob/883a616f0bf3258f1898e0fad0c3707c630f81b0/quiche/src/lib.rs#L3975-L3976
I may be misunderstanding some nuance of QUIC's internal state tracking, but for me the ideal API would be an immediate packet construction helper, similar to how
retry
ornegotiate_version
work:A bonus would be if it could somehow handle
data
andout
being overlapping, to allow adding the header and encrypting in-place. I'm not familiar enough with rust's slice type to know if that's easy or not. Otherwise it would be another fn:Thanks for reading! I'm happy to open a PR for this if the API seems workable.