miércoles, 16 de julio de 2014

Afinamiento del Garbage Collector para JBoss

Previamente a realizar cualquier cambio en la elección del garbage collector, ejecuta tu aplicación y deja que la JVM seleccione el collector mas adecuado, si es necesario redimensiona el Heap para mejorar el rendimiento. Si el desempeño no cumple tus objetivos realiza lo siguiente pasos:

1. Si la aplicación mantiene pequeños conjuntos de datos usa serial collector, habilítalo con: -XX:+UseSerialGC

2. Si la aplicación se ejecuta en un solo cpu y no tiene requerimientos de pausa por GC
· Deja que la JVM seleccione el collector
· Selecciona el serial collector –XX:+UseSerialGC

3. Si a) Si el máximo rendimiento es tu primera prioridad y b) no hay requerimientos de pausa o las pausas son de un segundo o mas pero aceptables
· Deja que la JVM selección el collector
· Selecciona el parallel collector con –XX:+UseParallelGC y opcionalmente habilita el parallel compaction con –XX:
+UseParallelOldGC

4. Si el tiempo de respuesta es más importante que el throuhgput y las pausas del garbage collection son cortas.
· Selecciona concurrent collector con –XX:+UseConcMarkSweepGC
Compartir:

Afinamiento de la JVM para JBoss

En las versiones mas recientes de la Sun Java Virtual Machine – JVM denominada también “HotSpot”, se ha implementado mejoras en dos aspectos importantes como son el proceso de garbage collector y en la parametrizacion de los pools de memoria que usan las aplicaciones denominado HEAP.

La configuración por defecto de la JVM normalmente es adecuada para iniciar un periodo de observación del comportamiento de las aplicaciones, si la elección de los parámetros por defecto no satisface los requerimientos entonces es posible realizar ciertas tareas de afinamiento de la JVM para mejorar el  desempeño de las aplicaciones.

Generaciones

El Heap, la memoria utilizada por la JVM para almacenar los datos se distribuye en los siguientes pools:



Se divide el Heap partiendo de la hipótesis de que gran parte de los objetos reside un corto tiempo en el heap. El Eden es el área donde se crean los nuevos objetos, el área de Survivor es el área donde se reciclan los objetos intermedios, el área Virtual es una área de reserva para el crecimiento del pool, en total existen dos áreas de Survivor y siempre uno debe estar disponible. El Tenured es un pool donde se almacenan los objetos mas antiguos, y el área permanente (Perm) es donde residen los objetos que estarán siempre o permanentemente en la memoria como son los datos necesarios para la operación de la JVM y aquellos que describen clases y métodos. La generación young, esta conformada por el Eden y los dos espacios de survivor

Garbage Collection

Muchos de los objetos “mueren jóvenes”, es decir en el la generación young, esto se representa en la figura 2, cuando el young esta lleno se produce un garbage Collection llamado minor Collection, que elimina de la memoria todos los objetos de la generacion young que ya no son alcanzables por ningun puntero de alguna aplicación que se este
ejecutando. En un ciclo tipico de minor Collection una fraccion de los objetos que residen en el young son movidos al tenured. Cuando el tenured se llena ocurre un major collection que resulta en una recoleccion de objetos inalcanzables de todo el head, un minor Collection normalmente es mucho mas rapido que un major Collection que hace
un barrido de todo el pool de heap.



Medidas de Desempeño del Garbage Collection

Las siguiente son medidas de desempeño a tener en cuanta:

Throughput: es el porcentaje del total de tiempo que no se hace garbage collection sobre periodos largos de tiempo. El throughput incluye el tiempo gastado en hacer asignaciones.

Pausas: son las veces que la aplicación parece no responder porque el garbage collection esta ocurriendo.

Footprint: es el trabajo conjunto de un proceso, medido en caché de páginas y líneas

Promptness: es el tiempo transcurrido entre que el objeto será desalojado (muere) y cuando se disponga de la memoria

Las medidas más importantes son las dos primeras y sirven para priorizar objetivos.

Garbage Collector Disponibles

Serial Collector

Usa un solo thread para el proceso de garbage collection, es ideal para maquinas con un solo cpu. Para maquinas con mas de un cpu es conveniente cuando se mantiene un conjunto pequeño de datos aproximadamente menor a 100 MB.

Se selecciona por defecto en ciertas plataformas pero se puede habilitar con
–XX:+UserSerialGC.

Parallel Colector

Ejecuta los minor collection en paralelo, para los major collection usa un solo thread presenta un mejor desempeño en maquinas con varios cpu, es ideal para aplicaciones que mantienen medianos o grandes conjuntos de datos. En sistemas operativos multithread con jdk 5.0 se selecciona por defecto sin embargo se puede seleccionar explícitamente con: –XX:+UseParallelGC

En J2SDK 5.0 fue introducida la característica de parallel compaction, esta permite ejecutar los procesos major collection en paralelo. Se habilita con la opcion:
-XX:+UseParallelOldGC

En maquinas con N cpus, el parallel collector usa N threads, el numero de garbage collector threads puede controlarse con: -XX:ParallelGCThreads=<N>

En maquinas con un solo cpu, el serial collector podría ser mejor por el overhead que cusa la sincronización de los threads en paralelo, cuando se usa el parallel collector con un solo cpu.

Concurrent Collector

Ejecuta el trabajo del garbage collection concurrentemente con la aplicación para tener pausas cortas de garbage collection. Se usa en aplicaciones que mantienen medianos o grandes conjuntos de datos. Es conveniente cuando el tiempo de respuesta es mas importante que el throughput en general (esta técnica puede reducir el desempeño de la aplicación). Se habilita con –XX:+UseConcMarkSweepGC
Compartir:

Afinamiento de la Memoria de Linux para JBoss

Parámetro shmmax

El parámetro shmmax es usado para definir el tamaño máximo en (bytes) para el segmento de memoria compartida. Es conveniente incrementarlo para aplicaciones que usen grandes cantidades de memoria. Se recomienda definirlo en 2GB por defecto en algunas distribuciones de RedHat Linux es de 32MB. Tener presente que el tamaño máximo de este parámetro es de 4GB.

Hugepages

Hugepages puede potencialmente proveer un alto desempeño a partir del hardware reduciendo el uso del cache del CPU. Los beneficios generalmente lo obtienen las aplicaciones que usan cantidades grandes de memoria para almacenar sus datos. Para que las aplicaciones puedan explotar esta opción, la característica de Hugepages debe ser soportada por el sistema operativo.

Para descubrir si el kernel soporta Hugepages, ejecuta:

[root@localhost ~]# grep Huge /proc/meminfo
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 4096 kB
[root@localhost ~]#

Para hacer que el HEAP use una huge page de al menos 2GB, podemos configurar los parámetros anteriormente descritos de la siguiente manera:

Configura shmmax dinámicamente mediante:

#echo 2147483647 > /proc/sys/kernel/shmmax

O puedes setearlo en el archivo /etc/sysctl.conf, agregando la siguiente linea:

kernel.shmmax = 2147483647

Configura el parámetro nr_hugepages a 1000 dinámicamente, ejecutando el siguiente comando:

#echo 1000 > /proc/sys/vm/nr_hugepages

O agrega el en el archive /etc/sysctl.conf la siguiente linea:

vm.nr_hugepages = 1000

En las opciones de la JVM de Sun agrega la siguiente opción: XX:+UseLargePages

Es necesario que reinicies el sistema para asignar las “Hugepages”, porque las Hugepages requieren grandes áreas de memoria física contigua, es decir la memoria física debe ser mapeada a las páginas que la requieran. Es recomendable configurar estos parámetros en el archivo /etc/sysctl.conf para asignar la Hugepages en  tiempo de inicio del sistema.
Compartir:

Afinamiento de IO de Linux para JBoss

Parametro tcp_keepalive_intvl

La variable tcp_keepalive_intvl le dice al kernel cuánto tiempo es la espera de una respuesta en cada KeepAlive. Este valor muy importante cuando se intenta calcular cuánto tiempo pasará antes de que una conexión se de por “muerta”.

La variable tiene un valor por defecto de 75 segundos. Los valores por defecto de tcp_keepalive_probes y tcp_keepalive_intvl pueden ser utilizados para obtener el valor por defecto que tomará de tiempo antes de que la conexión se de por perdida.

Con los valores por defecto de envío de 9 paquetes con 75 segundos para cada uno, que se tardaría aproximadamente 11 minutos antes de la conexión agote el tiempo, contando a partir del momento en que se inicie el sondeo puede pasar 2 horas desde la última vez que se vio tráfico en la conexión, este tiempo esta controlado por el parámetro tcp_keepalive_time que tiene un valor por defecto de 7200 (2 horas) segundos no se recomienda disminuirlo para evitar trafico en la red.

Se recomienda 15 segundos en este parámetro, para cambiarlo ejecuta el siguiente comando:

[root@localhost ~]# echo 15 > /proc/sys/net/ipv4/tcp_keepalive_intvl

Parametro tcp_keepalive_probes

La variable tcp_keepalive_probes le dice al kernel cuántos KeepAlive TCP hay que enviar antes de que decida dar por terminada una conexión rota.

Esta variable tiene un valor, que en general no debe ser superior a 50. El valor por defecto es 9, antes de decirle a la aplicación que se ha interrumpido la conexión.

Se recomienda 5 intentos de valor en este parámetro, para cambiarlo ejecuta el siguiente comando:

[root@localhost ~]# echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes
Compartir:

Afinamiento del Kernel de Linux para JBoss


JBoss AS y la Java Virtual Machine pueden alcanzar un mejor desempeño en un sistema operativo afinado. En un entorno como Linux, es necesario ajustar algunos parámetros del kernel para tal fin.

Parametro file-max

El Parámetro file-max /proc/sys/fs/file-max, define el máximo numero de archivos que el kernel de Linux puede manejar. Este parámetro generalmente se afina para mejorar el manejo de archivos, incrementando el valor de /proc/sys/fs/file-max a un valor razonable como 256 por cada 4 MB de RAM. Ejemplo: para un servidor con 128 MB de RAM, asigna el valor 8192. Resultado de 128/4=32; 32*256=8192.

Para visualizar el valor por defecto ejecuta el comando:

#cat /proc/sys/fs/file-max

Para ajustar el valor para un servidor con 1GB de RAM, realiza los siguientes pasos desde una consola o terminal:

# echo "65536" >/proc/sys/fs/file-max

Para que no tengas que tipear otra vez el comando anterior después de reiniciar el servidor, configure el file-max en el archive sysctl.conf, sigue los pasos indicados:

Edita el archivo /etc/sysctl.conf y agrega la siguiente línea:
fs.file-max = 8192

Reinicia el servidor o el servicio de red, para que los cambio tengan efecto.
#service network restart

Parametro ulimit

Linux tiene un límite máximo de procesos por usuario. Esta característica nos permite controlar el número de procesos que un usuario puede tener en el servidor.

Para proveer mas desempeño, podemos configurar el límite de procesos para el súper usuario root a ilimitado. Edita el archivo .bashrc con vi /root/.bashrc y agrega la siguiente línea:

-u unlimited

Para que tenga efecto el cambio, cierra la sesión y reingresa al sistema como root

Para ver todos los limites que puedes imponer, ejecuta ulimit –a.

[root@localhost ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 16384
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 16384
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@localhost ~]#

Incrementa el limite de sistema que determina los archivos abiertos que pueden haber por instancia de un proceso en RedHat. Incrementa el valor de este limite en la sesión actual que ejecuta JBoss al valor recomendado de 8000, usando el comando:

[root@localhost ~]# ulimit -n 8000

Para confirmar ejecuta el siguiente comando:

[root@localhost ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 16384
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 8000
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 16384
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@localhost ~]#
Compartir: