18 abr

Mejorar el rendimiento de ZFS

El un post anterior explicamos como montar un zpool, con raidz con deduplicacion  más compresión, suele pasar que, por norma general instalamos el tinglado de ZFS por defecto, y normalmente al inicio funciona perfectamente y muy muy rápido, pero de repente un día nos damos cuanta que el rendimiento bajo sustancialmente. Entonces se nos empieza a caer el mito, el cielo se pone negro y todo se vuelve borroso.

Bueno, pues lo que voy a intentar es dar un poco de luz a ese panorama, explicando ciertos valores que son recomendables tocar en nuestro FreeBSD, para que gestione mejor todo el tinglado.

Vamos al lio.

Primero de todo, nos vamos a centrar en valores del sistema (Boot Loader Parameters), y van configurados en (/boot/loader.conf), nos debemos fijar como tenemos el sistema ahora, por si acaso debemos volver atrás, para eso utilizaremos.


sysctl -a

O podemos ver el valor establecido de aquella variable que queremos cambiar con


sysctl vfs.zfs.arc_meta_used

Primero de todo lo que vamos hacer es un comprobación muy sencilla, vamos a mirar como esta utilizando nuestro sistema la tabla ARC (La tabla ARC es el lugar en memoria, donde el sistema guarda los metadata y la cache de datos).

Debemos tener en cuenta que la memoria mínima que le asignemos al ARC será la que mantenga, todo lo demás desde mínimo al máximo, puede ser solicitado por cualquier otro proceso del sistema, la memoria de ARC no dispone de una prioridad alta, así que si algun proceso solicita memoria es más que probable que ARC ceda la que tiene utilizándose.

Esto nos sirve en el caso que dispongamos de otra aplicación que utilice un tamaño de memoria RAM mínimo para arrancar, podemos asegurarnos que el tamaño mínimo asignado a ARC dejara memoria suficiente para el resto de servicios

Memoria utilizada

sysctl vfs.zfs.arc_meta_used
vfs.zfs.arc_meta_used: 3839717456

Limite de la memoria permitida

sysctl vfs.zfs.arc_meta_limit
vfs.zfs.arc_meta_limit: 3887218688

Como podemos ver estamos al limite…, cosa que debemos cambiar.

Podemos hacer 2 cosas, o modificar el tamaño que utilizara la parte metadata de ARC añadiendo la variables vfs.zfs.arc_meta_limit o hacerlo de forma general, ya que en la tabla de ARC, guardaremos tanto los metadata como la cache de datos y que freebsd se lo gestione como buenamente quiera, pensemos que si modificamos por ejemplo el ARC_max a 4Gb y el arc_meta_limit a > 4GB,  es más que seguro que estemos forzando a que el sistema pase la cache de datos a disco, se puede aumentar el arc_meta, si tenemos activada la cache secundaria en disco SSD, que lo explicare como hacerlo en otro momento.

Bueno pues vamos a reservar un mínimo para todo el tinglado que expliqué del ARC.

Recomiendan utilizar esta regla para asignar un tamaño mínimo al ARC
4GB -> 512MB
8GB -> 1GB
etc

vfs.zfs.arc_min="8096M"

Contando que la máquina solo se dedique almacenar datos podemos aplicar las siguiente “reglas”, que por supuesto no son 100% fiables, debemos aplicar y ver como se comporta el sistema.

Ram x 0.5 – 512 MB


vfs.zfs.arc_max="3584M"

Ram x 2


vm.kmem_size_max="16G"

Ram x 1.5


vm.kmem_size="12G"

Una vez realizado esto debemos asegurarnos que los cambios que hemos hecho se comportan correctamente con el espacio libre del kernel, lo podemos hacer con el siguiente script.

#!/bin/sh

TEXT=`kldstat | awk 'BEGIN {print "16i 0";} NR>1 {print toupper($4) "+"} END {print "p"}' | dc`
DATA=`vmstat -m | sed -Ee '1s/.*/0/;s/.* ([0-9]+)K.*/1+/;$s/$/1024*p/' | dc`
TOTAL=$((DATA + TEXT))

echo TEXT=$TEXT, `echo $TEXT | awk '{print $1/1048576 " MB"}'`
echo DATA=$DATA, `echo $DATA | awk '{print $1/1048576 " MB"}'`
echo TOTAL=$TOTAL, `echo $TOTAL | awk '{print $1/1048576 " MB"}'`

Sumamos el espacio de utilización del kernel, más el utilizado por VDEV cache size, debemos controlar sobretodo vm.kmem_size ya que si nos pasamos con el valor, podemos tener un kernel panic al inicio del sistema, también debemos tener en consideración que vfs.zfs.arc_max, debe ser inferior a vm.kmem_size (ya que no solo ZFS utiliza la memoria), también debemos tener en cuenta, que si ponemos un valor muy alto en vm.kmem_size independientemente de vfs.zfs.arc_max, puede ser que el sistema no nos arranque, no hay problema, podemos cambiar en el gestor de arranque del sistema y asignar con (set vm.kmem_size = “512M”).

Si hemos cambiado los valores vfs.zfs.arc_max y vm.kmem_size el valor de kmem_size_max no se toma en consideración, pero se requiere ponerlo.

Seguimos con más opciones.


vfs.zfs.prefetch_disable="1"

Activar o desactivar esta opción, nos permite hacer que el sistema sea menos restrictivo a la hora de realizar las lecturas, de tal manera que la velocidad de lectura tiende a subir activandolo, este valor hace la función de precargar el siguiente bloque que el sistema predice que pueda ser leído, por supuesto en RAM , desactivarlo solo es recomendable para sistemas que tengan poca RAM.

Venga a por otro más


vfs.zfs.txg.timeout="5"

Este valor es el que controla el ZFS txg timeout, por defecto es 30 segundos, debemos cambiarlo si nos encontramos con cortes en la transferencia, ya que puede ser debido a esto,  normalmente el comportamiento por ejemplo en una linea de 1GB puede ser que  la tasa de trasferencia es oscilante,  o sea que por ejemplo se envían 100MB se para y de golpe envía 200MB etc etc, pensemos también que en el caso que tengamos activado la compresión, puede ser normal que baje la tasa de transferencia a disco mientras el sistema esta comprimiendo los datos, en ese caso lo que aumentara es la CPU

Ahora vamos a subir el numero de vnodes.

Los vnodes es un objeto dentro de la memoria del kernel que habla con la interfaz del sistema de ficheros( abre, lee, escribe, cierra,etc..), los vnodes pueden representar ficheros, directorios, colas….

De tal manera que en el caso que lleguemos al tope de vnodes que el sistema puede gestionar, pues nos encontraremos con la bajada de rendimiento del mismo. Con esto comprobamos su valor


sysctl vfs.numvnodes

Si nos quedamos sin “espacios” en la tabla nos saldrá en el messange.

La norma de freebsd es que 1 gb por cada 4Gb de RAM


vfs.zfs.write_limit_override=1073741824

Parámetros del sistema de ficheros

Ahora vamos a dejar el sistema base a un lado y nos centramos en opciones de ZFS.

Venga al lio!

Si los datos que tenemos en el raidz, no tiene una criticidad alta, podemos plantearnos quitar la opción de checksum, ya que la paridad del RaidZ yo nos proporciona una protección básica, de esta manera libramos carga del sistema de ficheros, pero como digo siempre y cuando los datos que tengamos no son críticos, sino en ningún caso debemos desactivar esta opción

Este cambio se realiza a nivel de pool de zfs, y debemos activarlo y desactivarlo en aquellos que nos interesen, de la siguiente manera.


sudo zfs set checksum=off myzpool

Podemos también desactivar a nivel de pool la opción atime, con esto evitamos que el kernel tenga que realizar updates de tiempo por cada acceso de lectura fichero, esto es necesario si o si, en el caso que los datos que tenemos en el zpool seas accesibles por diferentes servicios a la vez, como contra partida los snapshot ocuparan más.

Haremos


sudo zfs set atime=off myzpool

Ahora vamos a tocar lo que guardara ZFS en la cache, normalmente tendremos 1 cache, que es donde guardara por un lado los metadata de la tabla ARC y por otro cache de datos, si lo que queremos es ahorrar RAM, lo que podemos hacer es decirle a ZFS que solo guarde metadata en la cache. La buena practica seria activar 2 cache, en la primera cache, que va a RAM, le diremos que solo guarde la información metadata, y en la segunda cache que seria un disco rápido (SSD por ejemplo),  le diremos que guarde cache de datos.

Tenemos 3 opciones para “jugar” con la cache, all, metadata o none.

Mas adelante explicare como añadir un disco SSD, para utilizarlo de cache. Con el panorama actual lo dejaremos en all, pero para cambiarla seria.


zfs set primarycache=metadata myzpool

Como comento lo recomendable seria utilizar dos tiempos de cache, en el caso que dispongamos de un disco SSD para la segunda cache lo que haremos es decirle que la segunda cache que va a nuestro disco SSD. Tal que así


zfs set secondarycache=all myzpool

De esta manera lo que conseguimos es que se guarde en memoria la base de datos de metadata, y en el disco SSD se guarde la cache de datos más la metadata, la metadata solo se escribira en el caso que la cache de primer nivel se agote, cosa que no nos interesa, debemos evitar que llegue al disco, ya que en eso momento hemos muerto…. Game Over y a otra cosa mariposa.

Ahora toca la variable recordsize, el cambiar el valor de esta variable, se aplicara desde ese momento para los datos nuevos que añadamos.

Con esta variable le diremos la asignación de tamaño de bloque del pool, debemos tener cuidado con esto ya que la asignación de un tamaño grande, no es contraproducente a nivel de escritura, ya que si tenemos por ejemplo 128 k de bloque y escribimos bloques de 64k, realmente en el rendimiento no tendremos aumento de latencia, el problema nos lo podemos encontrar si la media de bloques escritos en nuestro sistemas es por ejemplo de 64k y tenemos el bloque de 128, por cada envía que hagamos enviaremos 128k, de los cuales 64k son datos vacíos que tiene que gestionar el sistema, a parte si  disponemos por ejemplo de una red de 100MB/s, si tenemos un tamaño de bloque ocupado de 128k, podremos enviar 700 veces por segundo.

Bueno aqui cada cual, yo personalmente lo tengo en 64k, el comando para modificarlo es


sudo zfs set recordsize=16k myzpool

Por ultimo podemos probar si existe alguna actualizacion de ZFS


sudo zfs upgrade my_poolsudo
sudo zpool upgrade my_pool

Con esto reiniciamos y comprobamos el rendimiento, podemos utilizar estos 3 sistemas para comprobar el rendimiento.

zfs-mon

atop -l  2

zpool iostat -v 2

Ale a disfrutarlo!!

06 mar

Bonnie++

El otro día me encontré con esta herramienta, que permite hacer un stress de los discos duros, tenemos diferentes herramientas del estilo, pero esta me pareció que cumplía bien lo que estaba buscando.

Bonnie++ esta disponible para Linux y Freebsd entre otros..

Para instalar en CentOS por ejemplo haríamos.

 yum install bonnie++
 

En freeBSD a través de ports, lo encontramos en

cd /usr/ports/benchmarks/bonnie++/
make
make install
make clean
rehash

Bueno básicamente bonnie++ nos proporciona 3 tipos de pruebas escrituras secuenciales, lecturas secuenciales y búsquedas aleatorias.
Podemos ver las opciones con

man bonnie++

Normalmente suelo utilizar esta linea que me parece bastante completa.

bonnie++ -d directorio -s 20g -n 1 -m localname -f -b -u user

Donde:

  • -d -> es el directorio de las pruebas
  • -s -> es el tamaño del fichero, nos recomiendan que sea como mínimo el   doble de la memoria RAM, de esta manera evitamos poder utilizar mucho la cache del sistema.
  • -n -> numero de ficheros que creara en múltiplos de 1024.
  • -m -> Nombre de la maquina, a modo informativo
  • -f -> Establece el control para las pruebas per-char IO tests
  • -b -> No escribir buffer
  • -u -> UID o usuario que utilizará

El resultado nos dará algo tal que:


Using uid:0, gid:0.
Writing intelligently...done
Rewriting...done
Reading intelligently...done
start 'em...done...done...done...done...done...
Create files in sequential order...done.
Stat files in sequential order...done.
Delete files in sequential order...done.
Create files in random order...done.
Stat files in random order...done.
Delete files in random order...done.
Version  1.96       ------Sequential Output------      --Sequential Input- --Random-
Concurrency   1     -Per Chr- --Block-- -Rewrite-      -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP      K/sec %CP K/sec %CP  /sec %CP
localname       32G  592276  77 198308  28             438462  25  2212 120
Latency              250ms   68195us                   533ms   14425us

Version  1.96      ------Sequential Create------        --------Random Create--------
localname           -Create-- --Read--- -Delete--        -Create-- --Read--- -Delete--
files                /sec %CP  /sec %CP  /sec %CP         /sec %CP  /sec %CP  /sec %CP
2                    776   6 +++++ +++  1419   7         1009   7 +++++ +++  1315   7
Latency               371ms     361us    1703us            2187us      48us    1456us

Sobre los resultados, tener en cuenta que en la primera linea, cuanto mas grandes sean los números mejor, al contrario que en la segunda linea, contra mas pequeños sea los números mejor

También puede ser interesante utilizar un atop o alguna herramienta de motorización, para comprobar el sistema durante el proceso