4 ms·
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 mul
by vlovich123 2mo 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)
- marginalia_nu 2mo agoio_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.
- vlovich123 2mo agoThat’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).
- marginalia_nu 2mo agoDBMS 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.
- vlovich123 2mo agoOf course it is and there is. Generally DBMSs are not handling 1 request at a time. Indeed such a DBMS wouldn’t be taken seriously. All of them support running run multiple requests concurrently. This is where io_uring is really important because it lets one thread schedule I/O to satisfy one request and resume processing a different request. Requests are also not I/O bound - you have a mix of CPU work to figure out where to issue the I/O and to manage the cache buffers on completion and read whatever information you need from the buffer pulled in. But sure, if all your DBMS is going to be doing is one point lookup at a time then there’s no benefit. But even non trivial SQL queries will surprise you because you can get complicated IO famous (eg checking the index which then tells you multiple blocks to look through which you can do concurrently). TLDR: unless your DBMS is ass slow, pread isn’t sufficient to get good throughput. And at that point it’s irrelevant if a single preadv is faster than io_uring.
- deleted 2mo ago[deleted]