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 →