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:
formato | tamaño (bytes) |
.csv original (sin compresión) | 3700635579 |
gzip | 585756379 |
bzip2 | 508276130 |
bzip2 (pbzip2-compressed) | 508782016 |
7z | 354107250 |
lzip | 354095395 |
lzo | 782234410 |
lz4 | 816582329 |
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):
(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.