historia - ¿Cómo maneja el kernel de Linux las solicitudes de E/S asíncronas(AIO)?
linux y sus versiones (1)
Estoy escribiendo un programa en C para leer datos de una unidad SSD leyendo directamente desde el archivo de dispositivo de bloque en bruto.
Estoy probando Linux AIO (estoy hablando de la API de Linux AIO, es decir, las funciones proporcionadas por linuxaio.h
, como io_submit(...)
etc., no la API POSIX AIO). Abro el archivo del dispositivo de bloque utilizando el indicador O_DIRECT
y me aseguro de que escribo en los buffers que están alineados con el tamaño del bloque.
Noté que Linux AIO es considerablemente más rápido que el uso de IO O_DIRECT
también con el indicador O_DIRECT
.
Lo que más me sorprendió es que el rendimiento alcanzado al emitir muchas lecturas aleatorias pequeñas de pocos KBs cada uno con Linux AIO es notablemente más alto que el rendimiento logrado al realizar una lectura grande (secuencial) de pocos MB utilizando I / O O_DIRECT
y O_DIRECT
.
Entonces, me gustaría saber: ¿por qué Linux AIO se comporta mejor que la E / S sincronizada? ¿Qué hace el kernel cuando se usa AIO? ¿El kernel realiza reordenes de solicitud? ¿El uso de Linux AIO resulta en una mayor utilización de la CPU que el uso de E / S síncronas?
Muchas gracias por adelantado
Respuesta corta: lo más probable es que la implementación de AIO sea "más rápida" porque envía múltiples IO en paralelo, mientras que la implementación sincrónica tiene cero o una E / S en vuelo. No tiene nada que ver con escribir en la memoria o con la ruta de E / S del kernel que tiene una sobrecarga adicional para las E / S síncronas.
Puedes verificar esto usando iostat -x -d 1 . Observe avgqu-sz (tamaño de cola promedio = el número promedio de E / S en vuelo) y % util (utilización = el porcentaje del tiempo que el dispositivo tuvo al menos una E / S emitida).
Respuesta larga:
El concepto de "más rápido" es complicado cuando se habla de E / S. ¿Significa "más rápido" mayor ancho de banda? ¿O es menor latencia? ¿O ancho de banda en un tamaño de solicitud dado? ¿O latencia a una profundidad de cola dada? ¿O una combinación de latencia, ancho de banda, tamaño de solicitud, profundidad de cola y muchos otros parámetros o la carga de trabajo? Supongo que aquí está tomando sobre el rendimiento / ancho de banda, sin embargo, es bueno recordar que el rendimiento de un dispositivo de almacenamiento no es una métrica de una sola dimensión.
Los SSD son dispositivos altamente paralelos. Un SSD está compuesto de muchos chips flash, cada chip tiene múltiples matrices que pueden leer / escribir de forma independiente. Los SSD aprovechan esto y realizan muchas E / S en paralelo, sin un aumento notable en el tiempo de respuesta. Por lo tanto, en términos de rendimiento, es muy importante la cantidad de E / S simultáneas que ve el SSD.
Entendamos lo que sucede cuando un subproceso envía una E / S síncrona: a) el subproceso pasa algunos ciclos de CPU preparando la solicitud de E / S (generar datos, calcular el desplazamiento, copiar datos en el búfer, etc.), b) la llamada al sistema es ejecutada (p. ej., pread ()), la ejecución pasa al espacio del kernel, y los bloques de subprocesos, c) el kernel procesa la solicitud de E / S y atraviesa las distintas capas de E / S del kernel, d) se envía la solicitud de E / S hacia el dispositivo y atraviesa la interconexión (p. ej., PCIe), e) la solicitud de E / S es procesada por el firmware del SSD, f) el comando de lectura real se envía al chip flash correspondiente, g) el controlador del SSD espera los datos, h) el controlador SSD obtiene los datos del chip flash y los envía a través de la interconexión. En este punto, los datos dejan el SSD y las etapas, como sucede a la inversa.
Como puede ver, el proceso de E / S síncrono está reproduciendo una solicitud de ping-pong con el SSD. Durante muchas de las etapas descritas anteriormente, en realidad no se leen datos de los chips flash. Además de esto, aunque su SSD puede procesar de decenas a cientos de solicitudes en paralelo, ve a lo sumo una solicitud en un momento dado del tiempo. Por lo tanto, el rendimiento es muy, muy bajo porque en realidad no está usando el SSD.
La E / S asíncrona ayuda de dos maneras: a) permite que el proceso envíe múltiples solicitudes de E / S en paralelo (el SSD tiene suficiente trabajo para mantenerse ocupado) yb) permite canalizar las E / S a través de varias etapas de procesamiento ( por lo tanto, desacoplar la latencia de la etapa del rendimiento).
La razón por la que ve que la E / S asíncrona es más rápida que la E / S síncrona es porque compara manzanas y naranjas. El rendimiento sincrónico se encuentra en un tamaño de solicitud determinado, poca profundidad de cola y sin canalización. El rendimiento asíncrono se encuentra en un tamaño de solicitud diferente, mayor profundidad de cola y con canalización. Los números que viste no son comparables.
La mayoría de las aplicaciones con uso intensivo de E / S (es decir, la mayoría de las aplicaciones como bases de datos, servidores web, etc.) tienen muchos subprocesos que realizan E / S síncronas. Aunque cada subproceso puede enviar como máximo una E / S en un momento dado, el kernel y el dispositivo SSD ven muchas solicitudes de E / S que pueden atenderse en paralelo. Las solicitudes de E / S de sincronización múltiple generan los mismos beneficios que las solicitudes de E / S asíncronas.
Las principales diferencias entre E / S asíncronas y síncronas se reducen a la forma en que E / S y procesos de programación y al modelo de programación. Tanto la E / S asíncrona como la sincronización pueden exprimir el mismo IOPS / rendimiento desde un dispositivo de almacenamiento si se hace correctamente.