Turso mide io_uring sin readahead: lección de rendimiento

Por qué Turso dejó io_uring sin readahead y qué midió

Turso abrió una PR para implementar readahead en su backend de io_uring y, antes de fusionarla, publicó benchmarks internos. El resultado: con una ventana de 32 páginas, las peticiones que llegan al disco cayeron de ~196.000 a ~16.300 en la query Q6 de TPC-H sobre una base de 1,2 GiB. Es decir, ~92% menos requests al dispositivo, aunque la base envió ~12% más SQEs (Submission Queue Entries).

El autor del post, del equipo de Turso, lo deja claro desde el inicio: el readahead «no es la implementación definitiva, pero excusa para medir io_uring». El artículo recorre paso a paso qué cambia cuando una base de datos SQLite-compatible escrita en Rust decide asumir el control del I/O en vez de delegarlo al kernel.

Qué es io_uring y por qué una startup de bases de datos se obsesiona con él

iouring es una interfaz de Linux introducida en el kernel 5.1 (2019) que reemplaza syscalls bloqueantes por anillos compartidos entre usuario y kernel: la aplicación encola operaciones y el kernel las ejecuta de forma asíncrona. En un modelo tradicional, cada lectura implica un read(2) que puede dejar el thread esperando; con iouring, el programa sigue trabajando y recibe los resultados cuando estén listos.

👥 ¿Quieres ir más allá de la noticia?

En nuestra comunidad discutimos las tendencias, compartimos oportunidades y nos ayudamos entre emprendedores. Sin humo, solo acción.

👥 Unirme a la comunidad

Turso mantiene dos backends de I/O para su base de datos:

  • syscall, basado en pread(2), el camino clásico.
  • iouring, que abre los archivos con ODIRECT, una opción que indica al kernel «escribe directo en el buffer del proceso, sin pasar por la page cache».

La elección de O_DIRECT no es trivial: le quita al kernel la posibilidad de hacer readahead por su cuenta, esa optimización silenciosa que anticipa las siguientes páginas cuando detecta acceso secuencial. Al renunciar a ella, Turso se compromete a implementar esa misma lógica en espacio de usuario. La PR probada es exactamente eso.

Los números del PR: 12% más SQEs, 92% menos requests al disco

Con PRAGMA prefetch_pages=0 (sin readahead), Turso emitió 195.207 SQEs durante Q6, y al dispositivo llegaron ~196.000 peticiones con un tamaño promedio de 4,37 KiB. Con una ventana de 32 páginas, las SQEs subieron a 218.212 (+23.005) pero las peticiones al disco bajaron a ~16.300 con tamaño promedio de 56,53 KiB y un porcentaje de merge del 91–93%.

La paradoja se explica por cómo funciona el block layer del kernel: si dos peticiones consecutivas están en la cola al mismo tiempo, el kernel las fusiona en una sola. Sin readahead, solo hay una SQE en vuelo a la vez, así que no hay nada que mergear; con readahead, 32 lecturas entran juntas y el dispositivo las procesa como un bloque contiguo.

El propio autor lo cuantifica con perf:

  • Sin readahead: 140 de 195.516 bios se fusionaron.
  • Con readahead: 202.539 de 218.493 bios se fusionaron, y el dispositivo recibió solo 15.951 peticiones.

La consecuencia es clara: el cuello de botella no era el ancho de banda del disco, era la cola de peticiones.

sqpoll: por qué un thread que gira sin parar puede ser tu peor enemigo

Turso usa io_uring con sqpoll (submission queue polling). Este modo elimina las syscalls de envío haciendo que un thread del kernel esté dando vueltas revisando si hay trabajo nuevo. Es eficiente en máquinas con CPUs libres, pero peligrosa cuando no las hay.

El autor cita un paper de Didona et al. (SYSTOR 2022) que midió exactamente este trade-off: con un solo NVMe y un solo core, sqpoll rinde apenas 13 KIOPS porque los dos threads (la query y el polling) compiten por el mismo CPU. Con un segundo core, el rendimiento se recupera por completo.

En su propio benchmark, con prefetch_pages=32 y sqpoll activo:

  • Wall time: 8,22 s
  • User time: 3,70 s
  • System time: 8,46 s (mediana de 7 corridas)

Que system time supere wall time solo es posible cuando dos threads ejecutan en paralelo. Al desactivar sqpoll (caer al ring «plain»):

  • Wall time: 8,62 s (un poco peor)
  • User time: 3,62 s
  • System time: 1,27 s

Conclusión del autor: «sqpoll es razonable cuando la máquina tiene más de un vCPU«. Si tu app ya consume CPU, el thread de polling compite con ella. En su entorno de prueba había 4 vCPUs y la query era single-thread, así que siempre quedó un core libre para sqpoll; en máquinas más ajustadas, el cálculo cambia.

Cache misses: el costo oculto de O_DIRECT

Al comparar io_uring (sin polling) contra syscall sobre la misma query:

  • io_uring: 8,55 s
  • syscall: 3,02 s

La diferencia es grande y el autor la buscó en las cache misses con perf:

Backend Cycles Instructions IPC Cache misses Miss rate
io_uring plain 5,374 B 21,497 B 3,999 10,666 M 13,255%
syscall 4,734 B 21,297 B 4,499 5,889 M 7,691%

iouring ejecuta casi las mismas instrucciones pero tiene 4,8 M de cache misses adicionales. La hipótesis: en una lectura buffered (la que usa syscall), el kernel copia los datos de la page cache al buffer del proceso y ese paso deja los datos «calientes» en las cachés L1/L2/L3. Con ODIRECT, el disco escribe directo al buffer del proceso sin pasar por la CPU, así que cuando la query toca esos datos más adelante, paga el cache miss.

El autor es honesto y aclara: «esta explicación es una hipótesis«. No trazó los misses hasta el paso de copia, solo observó el síntoma. Aun así, el número es lo bastante consistente como para tenerlo en cuenta si tu sistema usa O_DIRECT.

Qué significa esto para tu startup

Si tu producto depende de una base de datos con alto throughput de lectura secuencial, este caso de Turso te deja tres lecciones accionables:

  • Mide las peticiones al dispositivo, no solo las operaciones de tu app. El PR no optimizó el código de la query: optimizó la cola de I/O. Sin iostat y perf, no habría sido visible.
  • O_DIRECT no es gratis. Te ahorras la copia, pero pierdes readahead del kernel y «calentamiento» de cachés. Tiene sentido cuando tu patrón de acceso es aleatorio o cuando ya implementas tu propio readahead. Para acceso secuencial predecible, lee primero con la page cache.
  • sqpoll merece medición, no configuración ciega. Si vas a usar el modo polling de io_uring, valida que tengas un vCPU libre; en contenedores con CPU limitada puede hacer más daño que bien.

Para un founder técnico hispanohablante que monta infraestructura sobre Linux, el caso de Turso es una invitación a tratar el I/O como un sistema con sus propias colas, fusiones y costos de CPU, no como una caja negra que «simplemente lee del disco».

Por qué importa más allá de Turso

iouring ya es protagonista fuera del mundo de las bases de datos. En septiembre de 2025, ARMO publicó la investigación «Curing» (InfoQ, Bleeping Computer), un rootkit proof-of-concept que opera exclusivamente con operaciones iouring y evade las herramientas de seguridad que solo monitorizan syscalls. Google decidió desactivarlo por defecto en Android y ChromeOS. La interfaz ofrece 61 tipos de operaciones y una vía alternativa a los syscalls clásicos, lo que la vuelve simultáneamente atractiva para rendimiento y peligrosa para detección.

Lo que Turso mostró es la cara opuesta de la misma moneda: cuando se usa bien, io_uring colapsa 196.000 peticiones en 16.300 sin tocar una línea de la lógica de la query. Es el mismo poder, aplicado a un problema de ingeniería legítima.

Fuentes

¿te gustó o sirvió lo que leíste?, Por favor, comparte.

👥 ¿Quieres ir más allá de la noticia?

En nuestra comunidad discutimos las tendencias, compartimos oportunidades y nos ayudamos entre emprendedores. Sin humo, solo acción.

👥 Unirme a la comunidad

Daily Shot: Tu ventaja táctica

Lo que pasó en las últimas 24 horas, resumido para que tú no tengas que filtrarlo.

Suscríbete para recibir cada mañana la curaduría definitiva del ecosistema startup e inversionista. Sin ruido ni rodeos, solo la información estratégica que necesitas para avanzar:

  • Venture Capital & Inversiones: Rondas, fondos y movimientos de capital.
  • IA & Tecnología: Tendencias, Web3 y herramientas de automatización.
  • Modelos de Negocio: Actualidad en SaaS, Fintech y Cripto.
  • Propósito: Erradicar el estancamiento informativo dándote claridad desde tu primer café.

📡 El Daily Shot Startupero

Noticias del ecosistema startup en 2 minutos. Gratis, todos los días.

Share to...