io-uring icon indicating copy to clipboard operation
io-uring copied to clipboard

FAST_POLL support and switch to rustix

Open redactedontop opened this issue 7 months ago • 5 comments

Howdy!

2 things are proposed in this issue:

  1. Support IORING_FEAT_FAST_POLL, as it allows for performance gains (up to 20%) compared to both standard io_uring and epoll
  2. Switch to rustix, as the rustix-uring crate isn't as frequently updated as this one, and it'd be beneficial to switch over (cleaner and POTENTIALLY more performant code, with direct syscalls)

Thanks, Alex <3 PS: FAST_POLL is monoio's secret sauce for performance

redactedontop avatar May 28 '25 09:05 redactedontop

  1. IORING_FEAT_FAST_POLL is a feature flag, not a setup flag. if you think it needs "support", you may have misunderstood. see https://docs.rs/io-uring/latest/io_uring/struct.Parameters.html#method.is_feature_fast_poll
  2. We do support direct syscalls, and syscalls through libc are a feature. did you run into any issues, or do you think there's anything that's not "clean" or slow?

quininer avatar May 28 '25 10:05 quininer

One benefit of the rustix-uring crate is that if a feature isn't added yet, there are still ways to use the raw API to get around it. For example, neither this crate nor the rustix-uring have a proper API for IORING_REGISTER_NAPI (even though it released with 6.9, one year ago). But with the rustix-uring crate, I can still do this:

            use std::os::fd::AsFd;

            use rustix::io_uring as sys;

            const fn cast_ptr<T>(n: &T) -> *const T {
                n
            }

            fn execute<Fd: AsFd>(
                fd: Fd, opcode: sys::IoringRegisterOp, arg: *const core::ffi::c_void, len: u32,
            ) -> io::Result<()> {
                unsafe {
                    sys::io_uring_register(fd.as_fd(), opcode, arg, len)?;
                }
                Ok(())
            }

            let mut arg = sys::io_uring_napi::default();
            arg.busy_poll_to = 1 << 20;
            arg.prefer_busy_poll = 1;
            #[allow(clippy::expect_used)]
            execute(
                &self.io_uring,
                sys::IoringRegisterOp::RegisterNapi,
                cast_ptr::<sys::io_uring_napi>(&arg).cast(),
                1,
            )
            .expect("failed to register napi");

This is because the bindings themselves are a separate public API of the rustix crate, which are updated more frequently. I was just trying to switch to this crate as well, since it seems to be much more up to date (& more used), but I can't do that because of this. I guess this crate could also expose the raw sys API.

utkarshgupta137 avatar May 28 '25 10:05 utkarshgupta137

@utkarshgupta137 You can use this crate with rustix or any of your own linux api crates.

I thought rustix::io_uring::io_uring_register could accept an io_uring::IoUring fd, couldn't it?

let io_uring: io_uring::IoUring = ...;

rustix::io_uring::io_uring_register(
    io_uring.as_fd(),
    sys::IoringRegisterOp::RegisterNapi,
    &arg,
    1
).unwrap();

And, it would be even better if you are willing to open a PR for napi.

quininer avatar May 28 '25 11:05 quininer

@utkarshgupta137 You can use this crate with rustix or any of your own linux api crates.

I thought rustix::io_uring::io_uring_register could accept an io_uring::IoUring fd, couldn't it?

let io_uring: io_uring::IoUring = ...;

rustix::io_uring::io_uring_register( io_uring.as_fd(), sys::IoringRegisterOp::RegisterNapi, &arg, 1 ).unwrap();

And, it would be even better if you are willing to open a PR for napi.

Yeah, I was planning to add a PR for missing features. But I'm still iterating over the setup I want to use for my application, so it is better for me to do things manually now, before I try to write a proper API in the library.

utkarshgupta137 avatar May 28 '25 11:05 utkarshgupta137

@quininer 1. I've misunderstood. 2. It'd make code much cleaner.

redactedontop avatar May 28 '25 14:05 redactedontop