Table of Contents
Fetching ...

High-Performance DBMSs with io_uring: When and How to use it

Matthias Jasny, Muhammad El-Hindi, Tobias Ziegler, Viktor Leis, Carsten Binnig

TL;DR

The paper investigates when and how modern DBMSs can gain from Linux io_uring by examining storage-bound and network-bound scenarios. It shows that naive substitution yields modest gains, while end-to-end architectural design that exploits batching, asynchronous execution, and device-specific optimizations yields substantial throughput improvements. Through two case studies—a buffer-managed storage engine and a high-speed data shuffle over 400 Gbit/s networks—the authors derive practical guidelines and validate them with a PostgreSQL integration that achieves 11–15% improvements in table-scan performance. The work emphasizes that gains depend on workload characteristics and system bottlenecks, offering actionable steps for DBMS builders to leverage io_uring effectively. Overall, the study provides a concrete roadmap for designing I/O-intensive systems that harness io_uring’s unified, asynchronous, and batched I/O capabilities while remaining production-friendly.

Abstract

We study how modern database systems can leverage the Linux io_uring interface for efficient, low-overhead I/O. io_uring is an asynchronous system call batching interface that unifies storage and network operations, addressing limitations of existing Linux I/O interfaces. However, naively replacing traditional I/O interfaces with io_uring does not necessarily yield performance benefits. To demonstrate when io_uring delivers the greatest benefits and how to use it effectively in modern database systems, we evaluate it in two use cases: Integrating io_uring into a storage-bound buffer manager and using it for high-throughput data shuffling in network-bound analytical workloads. We further analyze how advanced io_uring features, such as registered buffers and passthrough I/O, affect end-to-end performance. Our study shows when low-level optimizations translate into tangible system-wide gains and how architectural choices influence these benefits. Building on these insights, we derive practical guidelines for designing I/O-intensive systems using io_uring and validate their effectiveness in a case study of PostgreSQL's recent io_uring integration, where applying our guidelines yields a performance improvement of 14%.

High-Performance DBMSs with io_uring: When and How to use it

TL;DR

The paper investigates when and how modern DBMSs can gain from Linux io_uring by examining storage-bound and network-bound scenarios. It shows that naive substitution yields modest gains, while end-to-end architectural design that exploits batching, asynchronous execution, and device-specific optimizations yields substantial throughput improvements. Through two case studies—a buffer-managed storage engine and a high-speed data shuffle over 400 Gbit/s networks—the authors derive practical guidelines and validate them with a PostgreSQL integration that achieves 11–15% improvements in table-scan performance. The work emphasizes that gains depend on workload characteristics and system bottlenecks, offering actionable steps for DBMS builders to leverage io_uring effectively. Overall, the study provides a concrete roadmap for designing I/O-intensive systems that harness io_uring’s unified, asynchronous, and batched I/O capabilities while remaining production-friendly.

Abstract

We study how modern database systems can leverage the Linux io_uring interface for efficient, low-overhead I/O. io_uring is an asynchronous system call batching interface that unifies storage and network operations, addressing limitations of existing Linux I/O interfaces. However, naively replacing traditional I/O interfaces with io_uring does not necessarily yield performance benefits. To demonstrate when io_uring delivers the greatest benefits and how to use it effectively in modern database systems, we evaluate it in two use cases: Integrating io_uring into a storage-bound buffer manager and using it for high-throughput data shuffling in network-bound analytical workloads. We further analyze how advanced io_uring features, such as registered buffers and passthrough I/O, affect end-to-end performance. Our study shows when low-level optimizations translate into tangible system-wide gains and how architectural choices influence these benefits. Building on these insights, we derive practical guidelines for designing I/O-intensive systems using io_uring and validate their effectiveness in a case study of PostgreSQL's recent io_uring integration, where applying our guidelines yields a performance improvement of 14%.

Paper Structure

This paper contains 94 sections, 17 figures, 2 tables.

Figures (17)

  • Figure 1: Performance comparison between traditional I/O interfaces and io_uring in a buffer manager and network shuffle. Naive use only yields modest gains, whereas designs that fully exploit io_uring more than double the performance.
  • Figure 2: io_uring architecture. The database system in user space communicates with the kernel via two shared ring buffers: the Submission Queue (SQ) for enqueuing I/O requests and the Completion Queue (CQ) for receiving results.
  • Figure 3: io_uring provides three execution paths: inline completion (2a), asynchronous execution via the poll set (2b), and a fallback to worker threads for blocking operations (2c). An optional SQPoll thread can submit requests without syscalls.
  • Figure 4: Overview of the buffer-managed storage engine design. Cold pages are evicted and written to disk freeing space that is used to cache frequently accessed pages.
  • Figure 5: YCSB throughput (100% uniform updates, one update per transaction) under different buffer manager designs and I/O execution modes. io_uring features and design optimizations are enabled incrementally from left to right, increasing transaction throughput from 16.5 k to 546.5 k TPS.
  • ...and 12 more figures