← Back to context

Comment by vlovich123

5 days ago

Do this with io_uring with the preadv syscall. It’ll be the same or faster (faster only if you can do something else while waiting for I/O or you can submit multiple requests simultaneously - a single io_uring will be basically identical)

io_uring is significantly faster for certain workloads, but you can't expect that merely running a syscall via io_uring will somehow magically make it faster.

Replacing single sycalls with their equivalents in io_uring is generally slower than just making the syscall directly. io_uring still uses syscalls after all.

io_uring generally only wins if you can amortize its overhead across multiple simultaneous operations. Implementing readahead would be such a case, except you can accomplish the same amortization with a single preadv instead, which again turns into a single syscall for multiple reads.

  • That’s not the only case. A read call makes your thread unable to do anything for the duration of the read. Io_uring lets that same thread continue to handle other requests which themselves might generate more I/O that gets amortized.

    The fair comparison isn’t 1 syscall on a single thread processing 1 task against io_uring. That would be insane because you clearly don’t have any performance requirements in such a workload already.

    The closest realistic equivalent would be using Tokio’s spawn_blocking to do that 1 syscall vs doing that syscall in io_uring. It’s probably still more efficient if your benchmark literally is the cost of 1 syscall at a time but not by as much and io_uring in poll mode doesn’t even enter the kernel so it can actually outperform the syscall offloaded to a background thread (even though yes under the hood it’s the same kernel code).

    • DBMS workloads aren't asynchronous like that though. There generally isn't anything you can do while you wait for the buffer pool to execute a read, since what you want to do next depends on the data being read.

      2 replies →