io_uring sin readahead: por qué la concurrencia importa más que el polling
Io_uring Without Readahead
Un PR para añadir readahead a Turso revela hallazgos sorprendentes sobre io_uring. Sin readahead, Turso emite una sola SQE a la vez, sin concurrencia, y el block layer no puede fusionar peticiones. Con readahead, 32 lecturas en vuelo permiten fusionar el 93% de las peticiones, reduciendo drásticamente las peticiones al dispositivo. El autor también descubre que el polling thread (sqpoll) consume el 65% de los ciclos de CPU, pero en una máquina con 4 vCPUs no compite con la query. Comparando con syscall, io_uring con O_DIRECT sufre más cache misses porque el DMA escribe directamente en el buffer del proceso, sin pasar por la caché de CPU. El artículo concluye con consejos sobre cuándo usar sqpoll y la importancia de batch submissions.
Con readahead activado, Turso emite 23.005 SQEs más y el dispositivo lee más bytes, pero recibe menos peticiones: el block layer fusiona el 93% de las peticiones.
- ComputerGuru
Artículo interesante, pero me dio un poco de ataque de pánico. Hacer benchmarks (con TPC o de otro modo) NO es la forma de determinar el enfoque correcto aquí; eso es estrictamente solo para bases de datos (típicamente RDBMS) que "poseen" efectivamente el hardware completo en el que se ejecutan. Una base de datos embebida podría usarse de esa manera si opera como backend para una aplicación CRUD pura que realiza ~cero renderizado del lado del servidor, análisis, validación, etc., y es esencialmente una interfaz asíncrona de HTTP a SQLite. Pero lo más probable es que una base de datos embebida se use y despliegue en máquinas (no necesariamente servidores) que sirven para muchos propósitos, y necesite rendir al máximo tanto dentro de los límites de los recursos disponibles para la máquina como en términos relativos, haciendo necesariamente concesiones que podrían sacrificar rendimiento por "valor" en términos de uso de CPU o memoria.
Esto no solo se aplica a los benchmarks, es una consideración esencial *cada vez* que tomas posesión de la caché del kernel, que es la única pieza en la pila que tiene visibilidad sobre el estado global y en la que se puede confiar para devolver memoria bajo presión y asegurar que todo funcione bien en conjunto. No se limita solo a bases de datos o incluso solo a memoria; por ejemplo, FreeBSD ha tenido más que su cuota justa de problemas que se remontan a que ZFS tiene una caché separada del kernel (a pesar de la integración más estrecha entre ambos y la presencia de varios mecanismos para abordar patologías [...]
- marginalia_nu
Si estás haciendo readahead contiguo en espacio de usuario, ¿por qué no usar simplemente preadv? Te limitará a hacer readahead hasta la siguiente página residente, pero al menos en mis experimentos con el índice de Marginalia, preadv supera a io_uring en todos los casos en los que puedes usar una sola llamada preadv para hacer la lectura completa.
- amluto
Me pregunto por qué la elección es entre syscalls y, específicamente, io_uring con O_DIRECT. AFAIK Turso es como SQLite y admite múltiples procesos accediendo a la misma base de datos, y esperaría que el buffering fuera una gran ventaja en algunas cargas de trabajo. ¿Qué hay de malo con io_uring sin direct? También existe el punto intermedio de RWF_DONTCACHE.
- ErroneousBosh
Esto ha pasado por mi feed y cada vez lo he leído como "Io_uring sin Radiohead", y quiero decir que podrías, pero ¿cuál sería el punto?
- weatherlite
¿Io_urine usa hilos amarillos?