-
-
Notifications
You must be signed in to change notification settings - Fork 384
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
feat: Faster UDP/IO on Apple platforms #1993
base: main
Are you sure you want to change the base?
Conversation
We found there wasn't much performance benefit, and was considerable difficulty taking advantage of, |
Bench on
Bench with this PR:
Surprised that |
Those tests tend to be extremely noisy, as the huge variance suggests. A targeted quinn-udp benchmark might be more useful. |
We've also found on neqo that multi-packet RX without multi-packet TX has limited benefits, since the RX batch size will be very small. |
I added |
How about using the https://github.com/quinn-rs/quinn/blob/main/quinn-udp/benches/throughput.rs |
With @mxinden's benchmark. Baseline:
Only
Both
Both sendmsg_x and recvmsg_x with
|
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.
LGTM.
Please squash all of the changes into a single commit?
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.
Impressive results. Great to see the MacOS _x
syscalls work for QUIC UDP IO.
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 we enable real GSO/GRO using these interfaces?
No. They are the equivalent of the |
…o feat-apple-datapath
Are you waiting on anything from me on this? |
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.
quinn-udp/benches/throughput.rs
will need more changes to still support non-apple platform. @larseggert I believe we will need to either run it multi-threaded, or use some kind of executor, e.g. tokio
. I can prepare a commit in the next couple of days. Sorry for missing this in earlier reviews.
Changes itself look good to me.
quinn-udp/benches/throughput.rs
Outdated
@@ -27,8 +27,12 @@ pub fn criterion_benchmark(c: &mut Criterion) { | |||
// Reverse non-blocking flag set by `UdpSocketState` to make the test non-racy | |||
recv.set_nonblocking(false).unwrap(); | |||
|
|||
let mut receive_buffer = vec![0; MAX_BUFFER_SIZE]; | |||
let mut meta = RecvMeta::default(); | |||
let mut receive_buffers = vec![[0; SEGMENT_SIZE]; BATCH_SIZE]; |
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.
We set the recv
socket to blocking above, to prevent potential race conditions.
recv.set_nonblocking(false).unwrap();
This is problematic on Linux, given that:
A blocking recvmmsg() call blocks until vlen messages have been
received or until the timeout expires. A nonblocking call reads
as many messages as are available (up to the limit specified by
vlen) and returns immediately.
https://man7.org/linux/man-pages/man2/recvmmsg.2.html
Given that quinn-udp
does not do sendmmsg
, send_state.send
will never send BATCH_SIZE
messages and thus recv_state.recv
will never return.
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.
@mxinden do you have a suggestion for a fix?
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.
@larseggert will be fixed with larseggert#1.
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.
Thanks!
Also, since all the tests are green, I guess quinn is missing a unit test to detect this breakage...
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.
Above referenced pull request addressing this issue moved to #2010.
Co-authored-by: Max Inden <[email protected]>
Co-authored-by: Max Inden <[email protected]>
Co-authored-by: Max Inden <[email protected]>
@Ralith can you do another round on this one? |
Once @mxinden's fix to the bench is in, I will rebase and squash this PR. |
Hey guys 👋, is there any chance Apple won't approve apps that are using those private syscalls in the App Store? They are notorious for doing so and even de-listing apps for using anything "undocumented". See 2.5.1 here: https://developer.apple.com/app-store/review/guidelines/ See one of such cases here: https://9to5mac.com/2019/11/04/electron-app-rejections/ How they will find out? Apple employs automated tools to scan apps for the usage of private APIs. If |
The use of the private syscalls is now behind a non-default feature. |
@larseggert should we add a big fat warning saying that if you enable this flag you will violate Apple ToS so it's only should be enabled if app is not distributed via App Store (or notarized for EU)? |
I have no opinion here - we don't distribute via the App Store. Could you make a suggestion on what you think would be good to add? |
Thank you for making it optional! It can be an issue to toggle code-paths like these with cargo features because they get aggregated across the entire dependency tree. Simply adding another dependency that also happens to depend on For some prior art, It looks like it is already abstracted away pretty well. Could we change this to a "plain" rustc cfg that needs to be set at build-time? |
This uses Apple's private
sendmsg_x
andrecvmsg_x
system calls for multi-packet UDP I/O.CC @mxinden