Io_uring Without Readahead
A technical analysis of implementing readahead in the io_uring interface for the Turso database reveals significant performance gains. By manually managing read concurrency, the application avoids the limitations of O_DIRECT and improves throughput during sequential data access.
Why it matters
Optimizing low-level I/O operations is critical for high-performance database systems, demonstrating how application-level tuning can overcome kernel-level constraints.
Someone opened a PR to implement readahead in Turso. It was a throwaway implementation, but a good excuse to measure io_uring and understand more about it.
Turso has two backends. syscall uses pread(2). io_uring uses io_uring, and opens the database file with O_DIRECT with no option to use buffered I/O. O_DIRECT takes away kernel readahead, so getting it back means implementing it in the application. 1
The PR's results are impressive. io_uring with an application buffer is faster. I want to understand why.
Without readahead, io_uring issues only one entry at a time. The problem is the lack of concurrency: each read waits for the previous one. The application knows that "hey, at this time, I need page 100", which means: Turso submits a read SQE for page 100, then waits for it. The scan continues. Now Turso needs page 101, so it submits a new read SQE that page.
Get smarter about the news
Sign up free for a feed built around what you actually care about, Dive Deeper research on any story, and the full text of every article.
Create free accountAlready have an account? Sign in