En mi entrada de la semana pasada, analizaba algunos de las herramientas y formatos de compresión más comunes, así como su velocidad y ratio de compresión. Aunque ello podría darnos una buena idea del rendimiento de estas herramientas, el análisis estaría incompleto sin investigar la descompresión. Esto es particularmente cierto para backups de base de datos ya que, en aquellos casos en los que el proceso de compresión se realice fuera de las máquinas de producción puede que no te importe tanto los tiempos de compresión. En tal caso, incluso si es relativamente lento, no afectará al rendimiento de tu servidor MySQL (o aquello que estés usando). El tiempo de descompresión, sin embargo, puede ser crítico, ya que podría influir en muchos casos en el MTTR (tiempo medio de recuperación) de todo tu sistema.

Entorno de pruebas

Utilicé el mismo dump MySQL de nodos de OpenStreetMap en formato CSV que mencioné en mi anterior post, y -dado que algunas de las herramientas usan el mismo formato (y deberían ser compatibles entre sí), pero resultaban en ratio de compresión distintos- elegí el fichero más pequeño de cada uno de ellos. He aquí una tabla con el tamaño comprimido por formato, como recordatorio:

formatotamaño (bytes)
.csv original (sin compresión)3700635579
gzip585756379
bzip2508276130
bzip2 (pbzip2-compressed)508782016
7z354107250
lzip354095395
lzo782234410
lz4816582329

Tenga en cuenta que aunque p7zip y lzip/plzip usan el mismo algoritmo, el formato de fichero es diferente. También tenga en cuenta que se han usando dos ficheros comprimidos distintos para bzip2: la razón de ello será aclarada más adelante.

El hardware era el mismo que en el último post: un Intel Quad Core i7-3770@3.40GHz con hyper threading y sin carga, exponiendo 8 cpus al kernel. 32 GB de ram. 2 discos duros clásicos (no SSD) de 3 TB en RAID 1. El sistema de archivos era ext4 con las opciones por defecto del sistema operativo. El sistema operativo ha cambiado, sin embargo, a CentOS 7.

La metodología fue similar a la utilizada anteriormente, para cada herramienta se ejecutaba el siguiente comando varias veces:

$ time [tool] -d -c < nodes.csv.[format] > nodes.csv

Excepto en el caso de dd y 7za, donde la sintaxis varía ligeramente.

El archivo final se almacenaba en una partición diferente del mismo RAID. De este fichero se comprobaba su corrección (que el archivo sin comprimir fuera exactamente igual al original) y borrada tras cada ejecución. No repetiré aquí mi disclaimer sobre el uso de la cache del sistema de archivos, pero he añadido los resultados de dd como referencia.

Resultados globales

Esta es mi tabla de resultados finales; el análisis y discusión de los mismo siguen a continuación:

método de                  tamaño        ratio de    mediana del tiempo  velocidad de   Uso %CPU
compresión                 comprimido    compresión  de descompresión 	 descompresión
                           (bytes)       (%)         (segundos)          (MB/s)
dd                         3700635579    100.00%       9.996              353.061       100 -  43
gzip                        585756379     15.83%      17.391              202.933        99 -  26
bzip2                       508276130     13.73%      55.616               63.457       100 -  45
pigz                        585756379     15.83%       7.115              496.023       172 -  62
pbzip2 (bzip2-compressed)   508276130     13.73%      50.760               69.527       170 -  64
pbzip2 (pbzip2-compressed)  508782016     13.75%       9.904              356.341       794 - 185
lzip                        354095395      9.57%      38.682               91.236       100 -  47
7za                         354107250      9.57%      28.070              125.729       157 -  95
plzip                       354095395      9.57%      19.791              178.324       345 - 177
lzop                        782234410     21.14%       6.094              579.127       136 -  47
lz4                         816582329     22.07%       3.176             1111.209       100 -  78

Estos datos pueden verse más fácilmente, como es habitual, en un gráfico bidimensional. En este caso, el eje X axis representa la mediana de la velocidad de descompresión en MB/s (más es mejor) y el eje Y representa el porcentaje del tamaño comprimido sobre el tamaño original (menos es mejor):

Análisis de las diferentes herramientas de compresión: ratio de compresión vs. velocidad de descompresión
(no está representado dd, ya que el aparecería con un ratio de compresión del 100%)

El uso de CPU se monitorizó cada segundo, así como el uso de memoria, que en ningún test para ninguna de las herramientas fue superior a 1MB.

En este caso he representado la función y = x*0.01+12 sobre los puntos y, aunque hay una clara tendencia de que mejores ratios de compresión requieren más tiempo de descompresión, la correlación es más débil que en el caso de la compresión.

La última cosa que me gustaría remarcar sobre los resultados globales es que no se han probado variaciones en los parámetros para la descompresión ya que en la mayoría de los casos hay pocas o ninguna opción para este proceso, y los algoritmos harán esencialmente los mismo para un archivo que fue creado con --fast que para otro que fue creado con --best.

Descomprimiendo los formatos gzip y bzip2

Sin ser precisamente sorpendente, el archivo gzip tardó menos tiempo en ser descomprimido que bzip con las herramientas GNU genéricas (56 segundos vs. 17). Utilicé GNU gzip 1.5 y bzip2 1.0.6. Ya comenté todo lo que quería comentar sobre las ventajas de y desventajas de usar las herramientas más estándar, así que no me volverá a repetir aquí, pero quería reiterar la idea de que gzip sigue siendo una buena utilidad para compresión rápida cuando no hay alternativa, ya que obtuvo un throughput de casi 203 MB/s al descomprimir nuestro fichero de pruebas.

Por supuesto, el siguiente paso era probar la descompresión en paralelo, y para ello disponía de pigz 2.3.1 y pbzip2 v1.1.6. Como nota al margen, me gustaría mencionar que, en el momento de escribir estas líneas, no había paquetes rpm para pbzip2 en CentOS 7 ni en la distribución base ni en EPEL (el cuál está actualmente en beta para la versión 7). Utilicé el paquete para RHEL6.

Sin embargo, cuando eché un vistazo a los resultados de pigz me pude dar cuenta de que, aunque ciertamente había una mejora en la velocidad (un poco más de 7 segundos), ésta no es tan dramática como la mejora 4x+ que observamos en la compresión. Además, si miramos al uso de la cpu, nos podemos dar cuenta de que el máximo uso de %CPU nunca supera el 170. Me dí cuenta que la razón de esto leyendo la documentación: aunque pigz usa varios hilos para la E/S de lectura y escritura, es incapaz de paralelizar el algoritmo básico de descompresión de gzip. Las mejora sobre el gzip estándar -en cualquier caso- están ahí, con casi 500 MB/s de ancho de banda de descompresión.

Cuando probé pbzip2, en mi primer intento, me di cuenta de que no había paralelización en absoluto, y que los tiempos eran esencialmente los mismos que el bzip2 normal. Buscando respuestas en la documentación encontré que la razón de ello era que la descompresión en paralelo era posible (al contrario que con gzip), pero sólo para archivos creados por el propio pbzip2.. En otras palabras, tanto bzip2 como pbzip2 crean archivos con un formato compatible (pueden ser descomprimidos por la otra utilidad), pero la paralelización sólo es posible si se crean y descomprimen con pbzip2. Para probar este segundo caso, utilicé el mejor archivo comprimido obtenido en mis resultados previos (que era ligeramente más grande que el creado con bzip2) y volví a probar los tests. Ésta es la razón por la cual hay dos filas diferentes en los resultados globales para pbzip2.

En ese segundo escenario, pbzip2 era una verdadera mejora sobre bzip2, obteniendo rates de descompresión de 356 MB/s, aproximadamente equivalentes a los resultados de una copia directa mediante el sistema de archivos.

Como era de esperar, el uso de múltiples hilos de descompresión es una clara ventaja en sistemas SMP, con los habituales avisos por los recursos extra consumidos y el hecho de que, en la realidad, como acabamos de ver, no siempre es posible para todos los formatos de archivo.

Descompresión Lzma

El siguiente grupo para poner a prueba son las herramientas basadas en lzma: Lzip 1.7, p7zip 9.20 y plzip 1.2-rc2. De nuevo, lzip no estaba disponible en EPEL-7, así que se usó la versión de RedHat6, y plzip fue compilado a partir del código fuente, tal y como hicimos anteriormente.

El algoritmo Lzma se había clasificado como lento pero con muy buena compresión en nuestros resultados anteriores. Se puede extrapolar un resultado similar para la descompresión: tanto lzip como 7za proporcionan tiempos de descompresión de unos 30 segundos, con anchos de banda cercanos a los 100 MB/s. Aunque p7zip parece un poco mejor paralelizado que lzip (con %cpu llegando a los 150), ambos proporcionan esencialmente un algoritmo de descompresión monohilo. Plzip proporciona una mejor paralelización, alcanzando un uso de la cpu del 290%, pero el throughput nunca supera los 200 MB/s.

La evaluación general es que son claramente mejores herramientas que los gzip y bzip2 monotarea, ya que proporcionan unos anchos de banda de descompresión similares pero con unos ratios de descompresión mucho mejores..

Herramientas “rápidas”: lzop y lz4

Finalmente nos quedan las herramientas de compresión y descompresión rápidas, en nuestros tests, lzop v1.03 y lz4 r121. En este caso podemos testificar las afirmaciones de que lz4, aunque proporcionan unas velocidades de compresión similares a lzop, es más rápido en la descompresión: casi dobla la velocidad (580 MB/s de lzop contra los 1111 MB/s de lz4). Obviamente, la única razón por la cual estos resultados son posibles es porque el sistema de archivos está siendo utilizado, así que tomad estos resultados con la debida precaución. Pero muestran la clase de ancho de banda de descompresión que se puede obtener cuando la latencia de disco no es el cuello de botella.

Cuando el tiempo de los tests es tan pequeño, recomendaría repetirlo con tamaños de archivo mayores o limitando los efectos de la caché del sistema de archivos. Dejaré esto como un ejercicio a realizar por el lector.

Conclusiones

Aparte de las limitaciones encontradas en las distintas herramientas respecto a la paralelización en descompresión (pigz, pbzip2), no se han encontrado resultados muy extraños. Las herramientas de compresión rápida son rápidas en descompresión (me he vuelto un fan de lz4) y las herramientas de mejor compresión son más lentas (plzip parece funcionar muy bien si no se está restringido por el tiempo de ejecución y el uso de la CPU). Como siempre, mi recomendación es probar siempre en el propio entorno, con los archivos y máquinas propias, antes de sacar conclusiones prematuras.

¿Qué herramienta de compresión usas para MySQL (o cualquier otro sistema de base de datos)? Déjame un comentario aquí o en Twitter.

¿Qué herramienta de compresión debería usar para las copias de seguridad de mi base de datos? (Parte II: descompresión)
Etiquetado en: