Azure Native Qumulo ahora disponible en la UE, el Reino Unido y Canadá: Más información

Transferencia de datos descargados de almacenamiento de Windows (ODX) y el caso de la captación previa faltante

Escrito por:
Cómo un cliente experimentó un rendimiento más lento de lo esperado al comparar LECTURA/ESCRITURA estándar con ODX, y cómo el equipo de ingeniería aprovechó las métricas de Qumulo Core, el ciclo de lanzamiento rápido y la experiencia de actualización perfecta para descubrir y resolver el misterio.

Cómo un cliente experimentó un rendimiento más lento de lo esperado al comparar LECTURA/ESCRITURA estándar con ODX, y cómo el equipo de ingeniería aprovechó las métricas de Qumulo Core, el ciclo de lanzamiento rápido y la experiencia de actualización perfecta para descubrir y resolver el misterio.

¿Qué es ODX (Transferencia de datos descargados de almacenamiento de Windows)?

Windows Storage Offloaded Data Transfer (ODX) es parte del protocolo del bloque de mensajes del servidor (SMB) en el que puede indicarle al sistema de archivos Qumulo que copie una parte de un archivo de un archivo a otro sin enviar los datos a través de la máquina cliente. ODX mejora el rendimiento de la copia muy parecido a la copia del lado del servidor (SSC). Elimina la latencia de la red entre el cliente y el servidor, y permite que Qumulo Core optimice los tamaños de E/S y el almacenamiento en búfer. al comparar ODX frente a SSC, los resultados de nuestras pruebas internas muestran que ODX es 7 veces más rápido y SSC 4 veces más rápido que la típica secuencia de LECTURA/ESCRITURA que se produce al copiar un archivo a otra ubicación en el mismo servidor.

Leer misterio de latencia

En 2021, enviamos soporte ODX para Qumulo Core versión 3.0.0 o superior. Poco después de que enviáramos, un cliente informó que el rendimiento de ODX era más lento de lo esperado.

Sabiendo que ODX lee de un archivo y escribe en otro, inicialmente sospechamos que el problema era el rendimiento de escritura. Por lo general, las operaciones de lectura toman un máximo de unos pocos milisegundos (gracias Almacenamiento en caché y captura previa de SSD!). Sin embargo, cuando miramos el latencia de lectura, vimos que era una parte más grande de la latencia ODX de lo que podríamos esperar: del orden de 25 ms (aprox.), con picos más altos de 40 o 50 ms. ¿Qué está pasando con eso? Aquí hay una visualización de la vida útil de la fase de lectura de una operación ODX:

Examinamos nuestros datos de rendimiento de series temporales de baja granularidad que recopilamos a través de nuestra canalización de monitoreo en la nube. En promedio, nuestra tasa de aciertos de caché de RAM y las métricas de latencia se veían bien. Pero entonces, ¿por qué las lecturas específicas de ODX eran comúnmente lentas?

la primera pista

A medida que nos acercábamos a descubrir la causa raíz, necesitábamos métricas de mayor granularidad que fueran específicas para una sola carga de trabajo ODX en este clúster, sin el ruido de otras operaciones. Por suerte, tenemos una herramienta, llamada trigger</var/www/wordpress>, which we built internally, which collects this kind of distributed performance data when needed. We worked with our customer to profile some specific ODX sequences, and used trigger</var/www/wordpress> to collect data during those sequences. We learned a couple of things. (Refer to Figura 1 y XNUMX, above.)

En cada operación de lectura, la mayoría de los bloques estaban en la caché de RAM, pero a cada lectura le faltaba caché para algunos bloques. Cuando esto sucede, la transacción del sistema de archivos tiene que leer los datos de los propios dispositivos de almacenamiento. En este caso, las métricas nos dijeron que los datos estaban en discos giratorios.

[tipo de cuadro = "sombra"]Nota: En mi mente estaba pensando "por supuesto, tenían que ser los discos giratorios... es SIEMPRE los discos giratorios.” Debería haber sabido que las búsquedas son lo único que podría haber aumentado la latencia hasta 50 ms. Girando discos y no tengo la mejor relación. Tienen el hábito exasperante pero útil de exponer dolorosamente comportamientos no deseados en rutas de código sensibles al rendimiento.[/box]

Los discos giratorios pueden transmitir datos de manera eficiente cuando las solicitudes se ponen en cola en un orden contiguo; empezando por el principio de un archivo y leyendo hasta el final. Sin embargo, en este caso, solo nos faltaban unos pocos bloques de caché por operación de lectura ODX, lo que se muestra en el disco giratorio como muchas lecturas no contiguas. Esas son malas noticias para la latencia del disco giratorio.

Normalmente, las operaciones de lectura del sistema de archivos no experimentan este tipo de latencia de disco giratorio, porque tenemos un captador previo eficaz. El captador previo adivina lo que se leerá a continuación y lo carga en la memoria caché antes de tiempo. El captador previo tiene un patrón de E/S optimizado para leer desde discos giratorios.

Entonces, ¿por qué no funcionaba el captador previo?

Nuestro buscador previo tiene métricas que describen qué tan exitoso es en promedio. Estas métricas nos dijeron que todo lo que se precargaba se leía, pero algunos datos que el sistema de archivos leía no se precargaban... ¡eso es realmente extraño! ¿Quizás las operaciones ODX están leyendo fuera de orden o saltando al azar? El captador previo no funciona bien con IO aleatorias.

Verificamos los registros de operaciones para ver el patrón de IO. Los registros de operaciones son una herramienta de archivo de registro de texto que nos brinda información sobre cada operación, como el desplazamiento, el tamaño y el acierto o error de caché. Sin embargo, no habíamos anticipado que necesitaríamos los tamaños de lectura y las compensaciones de ODX en nuestros registros de operación y, como resultado, ¡ese código no se había conectado! Así que tuvimos que escribir más código y esperar una actualización...

Encontrar al culpable

En un par de semanas, enviamos el código nuevo y, gracias a nuestras increíbles actualizaciones, el cliente pudo actualizar su sistema de almacenamiento Qumulo a la última versión poco después. Volvieron a ejecutar la carga de trabajo de prueba para nosotros. ¡Usando el registro de operaciones mejorado, encontramos otro rompecabezas! Al leer los registros de operaciones (sentí que estaba en la matriz leyendo los números verdes), descubrimos que nuestro código de protocolo ODX enviaba al sistema de archivos solicitudes de lectura contiguas de 8650752 bytes cada una. Cuando hicimos los cálculos, resultó en 8 mebibytes + 256 KiB. ¡Pero! El registro de operaciones mostró que cada solicitud ODX en realidad solo obtenía 8388608 bytes del caché (exactamente 8 mebibytes).

Recuerdo que al principio mis ojos se nublaron... ¿estaba leyendo mal los números? ¿Cómo es que a cada solicitud le falta caché para solo 256KiB de los 8MiB que estaba solicitando? ¿Cómo es que el captador previo solo obtiene un subconjunto de cada solicitud? ¡Eso es imposible!

[tipo de cuadro = "sombra"]Nota: La primera etapa de cada error es la negación: creer que los datos son incorrectos. Afortunadamente, este no fue mi primer rodeo. Rápidamente sofoqué mi negación y comencé a preguntarme "¿cómo podría ser esto posible?" [/box]

Empecé a explicar cómo funciona el captador previo a mi compañero de trabajo que estaba trabajando conmigo en la investigación. El captador previo debe adelantarse a la carga de trabajo de lectura, de modo que el tamaño de E/S de la carga de trabajo de lectura no importe. El captador previo siempre obtiene datos en grandes porciones y de tal manera que la cola en los discos giratorios está bien ordenada para evitar búsquedas. Y entonces me di cuenta…trozos grandes... ¿Qué tan grandes son los fragmentos de captación previa? OH…tienen 8 MiB…espera, eso da miedo. ¿Y cómo se adelanta a la carga de trabajo de lectura? OH, iniciamos una captación previa por solicitud de lectura... espere... juntando esas dos cosas... si solo iniciamos una única captación previa por solicitud de lectura, y el tamaño del fragmento de captación previa es como máximo de 8 MiB, y el lector está leyendo fragmentos de 8MiB + 256KiB…entonces sí, obviamente, el precapturador nunca se adelantará…siempre precargará los siguientes 8MiB, dejando una cola de 256KiB sin almacenar en caché. WOW. (Bomba de puño). Está bien. Encontramos la pistola humeante.

Ejemplos de ilustraciones del problema de captación previa

misterio explicado

Descubrir el error es solo el comienzo. Inmediatamente surgieron tres preguntas que me vinieron a la mente:

  1. ¿Por qué no ocurre este mismo problema en las pruebas de lectura de nuestro sistema de archivos estándar?
  2. ¿Por qué ODX usa un tamaño de E/S de 8 MiB + 256 KiB, más grande que el tamaño máximo de E/S del precapturador y
  3. ¿Por qué nuestras pruebas de rendimiento específicas de ODX no detectaron esto?
1. ¿Por qué no ocurre este problema en las pruebas de rendimiento de lectura de nuestro sistema de archivos estándar?

Nuestro planificador de protocolos del sistema de archivos procesa todas las solicitudes de protocolos. El tamaño de solicitud de protocolo típico es 1MiB. Cuando recibimos solicitudes de lectura de protocolo, las procesamos y potencialmente combinamos solicitudes para optimizar el rendimiento de lectura. Naturalmente, tenemos un tamaño de E/S combinado máximo para estas solicitudes del sistema de archivos. Si deja que el tamaño de IO crezca demasiado, entonces la solicitud puede tener un cuello de botella en alguna cosa grande de un solo subproceso que estaba haciendo (por ejemplo, CPU, asignación de memoria). Por lo tanto, nuestro programador del sistema de archivos hace que la solicitud de lectura combinada máxima sea de 8 MiB, lo mismo que el tamaño máximo de E/S de nuestro buscador previo. Esto fue por diseño. Entonces, en estas cargas de trabajo, el precapturador está precargando todo, aunque nunca obtiene más de 8MiB por delante si el tamaño de E/S combinado también es de 8 MiB...(se rasca la cabeza...ese tampoco era un comportamiento intencionado...).

2. ¿Por qué ODX utiliza un tamaño de E/S de 8 MiB + 256 KiB?

La operación ODX en sí misma pasa por el programador, pero no envía su solicitud de lectura interna a través del programador. Entonces, ODX establecía el tamaño máximo de lectura de E/S que solicitaría, independientemente del programador.

Descubrimos que el tamaño máximo de E/S del programador y el tamaño máximo de E/S de ODX usaban diferentes funciones:

fs_target_transaction_size()
fs_max_transaction_size()</var/www/wordpress>

El programador estaba usando fs_target_transaction_size</var/www/wordpress>, which is a minimum of fs_max_transaction_size</var/www/wordpress> and 8MiB! Whereas the ODX code was intuitively using fs_max_transaction_size</var/www/wordpress> - which is computed, and turned out to be 8MiB + 256KiB.

Así que ahí estaba nuestra causa raíz. Arreglamos el código del protocolo ODX para usar fs_target_transaction_size</var/www/wordpress>, and voilá, no more uncached tails to the read requests.

3. ¿Por qué nuestras pruebas de rendimiento de ODX no detectaron esto?

Nuestras pruebas de rendimiento ODX sí logró, de hecho, exhiben el comportamiento de colas no almacenadas en caché. Pero, la actuación no fue tan mala; porque, en esta prueba de rendimiento, los datos eran lo suficientemente pequeños como para caber en la memoria caché SSD.

Mirando hacia atrás en Figura 1 y XNUMX (arriba), puede ver que la latencia de las lecturas de SSD es mucho menor que la del disco giratorio. Por lo tanto, no era tan obvio a partir de los resultados de las pruebas de rendimiento de primera línea que el buscador previo estaba haciendo lo incorrecto. La prueba no estaba verificando explícitamente las métricas del buscador previo.

Una vez que cambiamos la prueba de rendimiento para hacer un segundo paso de desalojar los datos del SSD y luego volver a leerlos desde el disco giratorio, el rendimiento principal fue significativamente peor de lo que debería haber sido, revelando el error. Solucionamos el error, observamos que esta prueba de rendimiento automatizada mejoró y envió la mejora en 2 semanas. Una vez más aprovechando las ventajas de Qumulo actualizaciones fáciles, nuestros clientes pudieron actualizar poco después de la corrección y obtener el rendimiento mejorado de ODX.

Más información

Artículos Relacionados

Ir al Inicio