Uso de fio: 3 pasos para una medición constante del rendimiento

fio para medir el rendimiento del sistema de archivos

En Qumulo usamos fio, una popular herramienta de evaluación comparativa de E / S de código abierto, para medir el rendimiento de nuestro sistema de archivos y detectar regresiones. Es una especie de navaja suiza, que admite una amplia variedad de modos y patrones IO; una de sus funciones útiles es el modo cliente / servidor, que puede dirigir el tráfico a un clúster de almacenamiento desde muchas máquinas simultáneamente. Esto es útil para simular muchas cargas de trabajo de almacenamiento del mundo real, como una granja de nodos de renderizado que escriben todos en un clúster de almacenamiento; esto nos permite caracterizar cuánto rendimiento puede sostener uno de nuestros clústeres.

Para detectar regresiones de manera confiable, es importante tener mediciones consistentes: a menos que un cambio de software haga que algo sea más rápido o más lento, un buen punto de referencia debería producir aproximadamente el mismo resultado cada vez. A continuación, presentamos tres prácticas recomendadas que seguimos para ayudar a obtener resultados uniformes y consistentes que facilitan la detección de desviaciones significativas.

1. Utilice el fio modo basado en el tiempo

El primero es bastante simple. fio tiene dos formas básicas de controlar la cantidad de cosas que hace cada trabajo: en función del tamaño y en función del tiempo. En el modo basado en tamaño, cada hilo escribirá (o leerá) una cantidad fija de datos y luego se detendrá. La cantidad total de datos transferidos por todos los trabajos, dividida por el tiempo que tardó en finalizar el último trabajo, es el rendimiento medido.

Este enfoque tiene un problema: no todos los trabajos terminan su trabajo al mismo tiempo. Las fluctuaciones ordinarias en la programación de procesos pueden significar que un trabajo obtiene una parte ligeramente mayor del rendimiento del clúster que otros, o más que su parte justa del ancho de banda de la red. Este diagrama muestra cuatro trabajos, cada uno de los cuales transfiere 10 gibibytes de datos:

medición del rendimiento de fio

Debido a que un trabajo tardó un poco más en completarse que los demás, nuestro intervalo de medición incluye una duración pequeña pero impredecible en la que solo se estaba ejecutando un trabajo. Esto introduce ruido en los resultados.

La solución a este problema son los parámetros del trabajo fio basado en tiempo y tiempo de ejecución. Por ejemplo, dando time_based = 1 y tiempo de ejecución = 60 s hará que todos los trabajos se ejecuten durante sesenta segundos y luego se detengan. Esto ayuda a garantizar que el intervalo de medición siempre tenga el clúster funcionando a plena carga, lo que resulta en mediciones más consistentes.

2. Introduce una barrera con exec_prerun

¡Los trabajos que terminan temprano o tarde no son la única fuente de fluctuación de medición! Hay otro problema más sutil: cada trabajo de fio no comienza a hacer su trabajo de inmediato. Primero, realiza algunas tareas de configuración y limpieza, recopila información sobre los archivos en los que trabajará y emite una gran cantidad de stat y otras solicitudes de metadatos. Esto puede llevar un poco de tiempo, especialmente si hay muchos archivos en el trabajo, y la cantidad de tiempo que tarda cada trabajo en prepararse puede variar por las mismas razones mencionadas anteriormente. Ejecutar cada trabajo durante un período de tiempo fijo es excelente, pero los trabajos aún no terminarán al mismo tiempo si no lo hacen comienzo ¡al mismo tiempo!

La solución a este problema es un poco más complicada, ya que la fio en sí no tiene ningún mecanismo para coordinar las horas de inicio de los trabajos. Afortunadamente, hace honor a su nombre como el "probador de E / S flexible" aquí, y proporciona exactamente el accesorio de navaja suiza que necesitamos: exec_prerun, un parámetro de trabajo que le permite proporcionar un comando que se ejecutará inmediatamente antes de que el trabajo comience a funcionar.

Es posible que esté familiarizado con una técnica básica de multiprocesamiento conocida como barrera: múltiples procesos pueden esperar en la barrera; la barrera sabe cuántos participantes esperar y no permitirá que ningún proceso continúe hasta que todos estén esperando.

Para la coordinación entre varias máquinas, creamos una implementación de barrera TCP simple en Python. No hay mucho que hacer: tenemos un servidor que espera N conexiones:

def servidor (punto final, N):

    s = socket.socket (AF_INET, socket.SOCK_STREAM)

    s.bind (punto final)

    escuchar (N)

    conexiones = []

    por _ in rango (N):

        conexiones.append (s.accept ())

    # ¡Una vez que estamos aquí, sabemos que todos están en la fiesta!

    por control, _ in conexiones:

        conn.sendall¡Vamos!)

Y un cliente que simplemente se conecta al servidor y espera que le digan que puede ir:

def cliente (punto final):

    s = socket.socket (AF_INET, socket.SOCK_STREAM)

    s.connect (punto final)

    # Esto se bloqueará hasta que el servidor responda:

    s.recv (3)

El código anterior está simplificado para mayor claridad; en realidad, por supuesto, hay más manejo de errores. Entonces todo lo que tenemos que hacer es poner algo como esto en nuestro archivo de trabajo:

exec_prerun =. / barrera_client.py

... y ahora nuestros trabajos no solo se ejecutarán durante la misma cantidad de tiempo, sino que comienzo corriendo al mismo tiempo. ¡Pero claro, hay más!

3. Restringir el búfer del cliente al límite fsync () patinar

Por último, existe una fuente de variabilidad que es específica de los trabajos que la escritura datos. De forma predeterminada en la mayoría de los sistemas operativos (y con fio), los datos escritos en archivos son Amortiguado; eso es un escribir() syscall colocará los datos en un búfer del sistema y luego regresará inmediatamente. El sistema operativo luego descargará de forma asincrónica estos datos al almacenamiento, ya sea un disco local o un almacenamiento remoto a través de una red.

¿Porque es esto importante? Bueno, el almacenamiento en búfer descuidado en un punto de referencia es una trampa. Si fio cree que ha escrito 300 GB de datos en 60 segundos, pero 50 GB de esos datos todavía se almacenan en búfer local porque las máquinas cliente tienen mucha RAM, lo que sobrestimará el rendimiento alcanzado por el almacenamiento bajo prueba. Para combatir esto, usamos el end_fsync parámetro de trabajo para garantizar que cada trabajo vacíe sus búferes después de terminar de escribir.

Desafortunadamente, esto tiene otro efecto secundario: el tiempo que lleva fsync () no está sujeto a fiotemporizador de trabajo - ¡otra fuente de variabilidad! Para empeorar las cosas, Linux de forma predeterminada utiliza un porcentaje de la memoria disponible del sistema para decidir cuándo comenzará el vaciado en segundo plano ... ¡y no todas las máquinas de nuestro grupo de clientes de laboratorio tienen la misma cantidad de memoria!

Sin embargo, resolver este problema es bastante fácil. Podemos decirle a Linux exactamente cuánto búfer usar:

sysctl -w vm.dirty_bytes = 2000000000

sysctl -w vm.dirty_background_bytes = 1000000000

En este caso, hemos especificado que el vaciado en segundo plano debe comenzar cuando el búfer total aumenta a 1 GB y, a 2 GB, debe comenzar a bloquearse. escribir() llamadas. Los valores exactos aquí no son críticos: solo deben ser 1) iguales en todos los clientes, 2) lo suficientemente pequeños como para que no sea posible gastar cantidades excesivas de tiempo en fsync ()y 3) lo suficientemente grande como para no obstaculizar el rendimiento. Estos valores funcionan bien para las pruebas que ejecutamos: los clientes aún conducen la carga a la velocidad máxima, pero el tiempo que se tarda en descargar al final es mucho más constante, lo que mejora la relación señal / ruido de la prueba.

(NOTA: Puede, por supuesto, usar E / S directa / sin búfer con fio, que es otra forma de escapar de este problema. Pero esto cambia las características de la carga de trabajo de otras maneras, y la mayoría de las aplicaciones usan E / S en búfer, por lo que queremos tener pruebas que simulen el caso común).

Conclusión

Así es como nos aseguramos fiolas pruebas de rendimiento basadas en resultados proporcionan resultados uniformes y uniformes. Tener una buena relación señal-ruido hace que sea mucho más fácil para nosotros detectar y corregir las regresiones de rendimiento y, por supuesto, también nos ayuda a rastrear las mejoras de rendimiento a medida que continuamos acelerando nuestro sistema de archivos.

Obtenga más información sobre fio.

Contáctanos

Solicite una demostración o una prueba gratuita de la plataforma de datos de archivos de Qumulo para ver una gestión de datos de archivos radicalmente simple a escala de petabytes. 

Suscríbete al blog de Qumulo para obtener historias de clientes, conocimientos técnicos, noticias sobre productos y mejores prácticas.

Comparta este artículo