miércoles, 16 de mayo de 2012

Solaris: Adaptative Replacement Cache and ZFS memory leak



Hace unos días acudí a un cliente el cual decía que sus servidores con Solaris 10 08/11 estaban consumiendo memoria de una manera excesiva (un total de 8 GB. de RAM física). La situación se producía en un grupo de dos servidores que utilizaban ZFS para montar unos Containers, mientras que en aquellos que cumplían la misma función pero no utilizaban ZFS, esto no se producía. Así que comenzando a destripar el alien, hice uso de unas de las fantásticas herramientas que Solaris provee para esto, mdb.
# echo ::memstat | mdb -k
Page Summary                Pages                MB  %Tot
------------     ----------------  ----------------  ----
Kernel                     632923              2472   30%
ZFS File Data              685607              2678   33%
Anon                       615745              2405   29%
Exec and libs                7442                29    0%
Page cache                   5817                22    0%
Free (cachelist)             3077                12    0%
Free (freelist)            144312               563    7%

Total                     2094923              8183
Physical                  2065101              8066
Como podemos ver, el kernel esta consumiendo el 30% de la memoria, mientras que ZFS un 33%, el resto son páginas mapeadas anónimas (29%). Fantástico, ya tenemos un centro: ZFS File Data.

Adaptative replacement cache (ARC):
Ustedes sabrán que el filesystem trabaja con cache, esto nos ahorra operaciones de I/O al momento de servir un dato, y por regla general aquello que es más utilizado se almacena en la cache, es por ello que existen distintos algoritmos tales como LRU (Last Recent Used), que mantiene en dicha memoria aquello que fue recientemente usado y uno bastante nuevo, desarrollado por IBM ARC (Adaptative replacement cache), este algoritmo realiza un seguimiento de las páginas recientemente usadas (MRU / Most Recently Used) y más frecuentemente usadas (MFU / Most Frecuently Used) y las almacena en la cache, como resultado tiene una mejor performance que LRU y es utilizado por ZFS para mejorar su performance.

Pero, ¿como funciona?, LRU, mantiene un stack en el cual las páginas recientemente usadas se añaden al final de la misma, esto es mejorado por ARC manteniendo una cache y dos listas paralelas, T1 (MFU) y T2 (MRU), para las páginas recientemente usadas y para las páginas frecuentemente utilizadas. Estas listas además se extiende con otra dos más, MFU Ghost o MRU Ghost, que es unida a la parte inferior de ambas listas. Estas dos últimas listas mantienen únicamente metadata de las entradas recientemente desalojadas de T1 y T2, pero que fueron removidas a fin de limpiar la cache. En caso de ser requeridas nuevamente, simplemente se vuelven a apuntar a T1/T2 de manera más eficiente que teniendo que volver a hacer una transacción de lectura del las unidades de storage.

Las listas en cuestión se encuentran definidas en uts/common/fs/zfs/arc.c:

La memoria que vemos que esta siendo utilizada como ARC, no debe preocuparnos, debido a que si un proceso la solicita, esta estará disponible para ser mapeada por el mismo, entonces, dejemos en claro que ES MEMORIA DISPONIBLE y no representa ningún problema para el sistema. Ahora veamos cuando esta reservando nuestro sistema como ARC:
# kstat -p -m zfs |egrep -i "arcstats.(size|c_max)"
zfs:0:arcstats:c_max    7507062784
zfs:0:arcstats:size     4140901208
Mediante kstat podemos ver, el tamaño actual de ARC, y el tamaño máximo. Si quisieramos limitar dicho tamaño debemos editar el archivo /etc/system. Por ejemplo queremos limitar nuestro ARC en nuestro servidor con 8GB de RAM física a 2 GB:
set zfs:zfs_arc_max = 0x80000000
Este cambio tomará efecto la próxima vez que reiniciemos el equipo. Si queremos realizar esto de manera dinámica debemos hacer uso de mdb:
# mdb -kw
 > arc_stats::print -a arcstat_p.value.ui64 arcstat_c.value.ui64 arcstat_c_max.value.ui64
ffffffffc00df578 arcstat_p.value.ui64 = 0xb75e46ff
ffffffffc00df5a8 arcstat_c.value.ui64 = 0x11f51f570
ffffffffc00df608 arcstat_c_max.value.ui64 = 0x3bb708000

 > ffffffffc00df608/Z 0x20000000
arc_stats+0x590:  0x11f51f570        = 0x80000000
Siempre podemos monitorear esto, para estar seguros de que el cambio fue aplicado, por ejemplo para ver el tamaño de la ARC en decimal, hacemos:
# echo "arc_stats::print -d arcstat_size.value.ui64" | mdb -k
arcstat_size.value.ui64 = 0t2147483648
Para mantenernos informados sobre las estadísticas de ARC y sumarizar dicha información existe una herramienta escrita en Perl, ARC Summary, que pueden descargar de aquí. Otra herramienta que es interesante conocer es arcstats, también escrita en Perl, y que puede ser descargada de aquí. Esta nos provee estadísticas como las siguientes, a fin de poder realizar un monitoreo efectivo de ARC:
# ~/arcstat.pl
    Time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
18:15:21  985M  100M     10   47M   14   53M    8    1M    3    11G   11G
18:15:22  137K     0      0     0    0     0    0     0    0    11G   11G
18:15:23  138K     0      0     0    0     0    0     0    0    11G   11G
18:15:24  138K     0      0     0    0     0    0     0    0    11G   11G
18:15:25  138K     0      0     0    0     0    0     0    0    11G   11G
18:15:26  138K     0      0     0    0     0    0     0    0    11G   11G
18:15:27  139K     0      0     0    0     0    0     0    0    11G   11G
18:15:28  140K     0      0     0    0     0    0     0    0    11G   11G
18:15:29  139K     0      0     0    0     0    0     0    0    11G   11G
18:15:30  140K     0      0     0    0     0    0     0    0    11G   11G
18:15:31  139K     0      0     0    0     0    0     0    0    11G   11G
18:15:32   33K     0      0     0    0     0    0     0    0    11G   11G
Referencias:
- ARC: A Self-Tuning, low overhead replacement cache - Nimrod Megiddo and Dharmendra S. Modha.
- Activity of the ZFS ARC - Brendan Gregg.

1 comentario:

  1. Estimado Facundo, tengo un problema real y concreto, me gustaria contactarme con usted. Le dejo mi correro leocasullo@hotmail.com

    ResponderEliminar