sexta-feira, 25 de julho de 2008

JVM Tuning

Buenas!

Devido ao longo tempo sem postar algo realmente decente e técnico, este post vai ser sobre o que estou fazendo atualmente, que é instalando e configurando os servidores de produção aqui da empresa juntamente com uma outra pessoa.

O nosso ambiente compreende um cluster de Tomcats fazendo Session Replication. Nossos servidores são de arquitetura Intel e do modelo QuadCore (apesar de uma plataforma Sun ser bem mais performática ainda mais com Java), então algumas configurações são específicas para isso e para o nosso modelo de aplicação e talvez não sejam as melhores para o seu caso, mas de qualquer forma gostaria de compartilhar um pouco das coisas que aprendi e que estamos utilizando.

JDK - Porque a versão 6?

Além de ser a última versão, ela é superior a versão 5 em questões de performance, as configurações default da vm já vem otimizadas para uma melhor performance de runtime e um garbage colector mais eficiente.

Esta versão, por ser mais recente, usa de uma maneira mais elevada o poder de multi-processadores ou multi-cores e da grande quantidade de memória existente. Exemplos disso são, o uso do GC em threads paralelas, podendo utilizar até 32 Threads (veja mais na tópico sobre Tuning), usa também do paralelismo para a promoção de objetos do Young para o Old (Permanent) conforme figura abaixo (caso queira aprender mais sobre como funciona o Heap Space do java leia este documento e este documento)JVM Tuning

Como muitos sabem, é possível mudar o comportamento da VM e parametrizar muitas coisas através das VM Options que são passadas na inicialização de um processo.
No nosso caso aqui, utilizamos alguns parâmetros, que vou listar abaixo com uma breve descrição:

[JVM Parameters]
-server - Para simplificar, este parâmetro te da uma melhor performance final do que inicial. Caso sua arquitetura seja 64bits, o server é o default, e para arquiteturas 32bits, o client é o default.
-XX:+UseLargePages - Se o seu SO permite Large Memory Pages habilite esta função e sete também outros parâmetros relacionados a isso. Para saber mais sobre LMP leia este documento.
-XX:+AggressiveOpts - Habilita algumas otimizações de código, que segundo a documentação, é pra estar habilitada como padrão nas versões futuras.
-XX:+UseFastAccessorMethods - Usa versões otimizadas para métodos get de tipos primitivos.
-XX:+UseParallelGC - Habilita o GC para abrir várias thread e atuar paralelamente.
-XX:ParallelGCThreads=6 - Número de thread que serão abertas para GC. Por default é aberto uma Thread para cada processador existente.
-XX:+UseParNewGC - Igual ao parâmetro UseParallelGC, porém para a área Young do Heap.
-XX:+UseTLAB - Usa Thread-Local para alocação de objetos

[MEMORY]
-Xms 512M - Parâmetro de memória que define o mínimo de memória para a aplicação.
-Xmx 8G - Parâmetro de memória que define o máximo de memória para a aplicação

[YOUNG]
-XX:NewSize=256M - Tamanho mínimo para a área Young do Heap.
-XX:MaxNewSize=1G - Tamanho máximo para a área Young do Heap.

[OLD]
-XX:PermSize=512M - Tamanho mínimo da área de objetos permanentes em memória.
-XX:MaxPermSize=2G - Tamanho máximo da área de objetos permanentes em memória.

Obs: não sete os valores máximos maiores que o -Xmx.

Para ver oturos parâmetros para VM veja esta página.
Para ver alguns exemplos de tuning de aplicações veja este link.
Leia também a FAQ sobre GC.

Ferramentas para Monitoramento de Aplicações

Segue abaixo algumas ferramentas que podem te ajudar a entender melhor sua aplicação e te ajudar a chegar a valores para os parâmetros. Existem muitas outras, outra hora comento sobre algumas mais específicas, mas comentei sobre essas apenas porque já vem com o próprio JDK, e vc as encontra em $JAVA_HOME/bin.

  • jps - Mostra os processos Java que estão rodando na máquina.
  • jinfo - Mostra informações sobre o processo java que está rodando, como bibliotecas que ele está usando, parametros de inicialização, parâmetros gerais da VM como aquelas que aparecem em System.getEnv().
  • jmap - Mostra informações sobre o uso de memória por uma aplicação, uso de cada divisão da Heap como a Young, Old, Tenure, Perm, etc.
  • jsadebugd - Este processo se junta ao processo passado como parâmetro e adiciona propriedades de debug ao processo em questão.
  • jconsole - JConsole é uma ferramenta visual que monitora e mostra várias informações sobre um processo, como uso de memória, número de threads, processamento, etc.
  • jstat - Coleta e loga informações estatísticas sobre performance.

Considerações

Conforme dito acima essas configurações são específicas para cada caso, então se precisar de ajuda sobre algumas configurações para um caso específico comente aqui, que responderei assim qeu possível.
Como tuning é um trabalho constante, a monitoração e o profiling são coisas extremamente importantes para que você consiga entender sua aplicação e definir o que usar e o que não usar.
Conforme for otimizando a nossa aplicação estarei fazendo update neste post, ou escrevendo novos posts se for o caso.
Enfim, espero que isso possa ajudar algumas pessoas, e com certeza vai me ajudar futuramente como documentação.

10 comentários:

A. M. disse...

Só agora você faz um post sobre Tuning de VM do 6???? Já ta pra sair o 7... Mas de qualquer forma... favorited!

Paulo Silveira disse...

Oi Jujo! Parabens pelo excelente post!!

Juliano D. Carniel (jujo) disse...

[a. m.] - =) só agora que tive tempo e saco.

[Paulo Silveira] - Valeu Paulo.

Anônimo disse...
Este comentário foi removido por um administrador do blog.
Anônimo disse...
Este comentário foi removido por um administrador do blog.
Avelino disse...

Juliano, estamos em fase e implementação de um servidor com replication session rodando tomcat aqui onde eu trabalho. Você um tutorial onde eu possa me guiar ?
Segue meu email: luizalberto.arquivos@gmail.com

gilmarcabral disse...

Ola!
Talvez voce possa ter ideia, do que possa ser. Atualmente tenho solucao de load balance de tomcat, porem utilizo o ldirectord do projeto LINUX VIRTUAL SERVER com isto tenho balanceamento de carga entre 4 tomcat.
Esta funcionando perfeitamente, so que ao passar dos dias, a JVM comeca a consumir toda memoria do servidor, os servidores cada possui 5 GB, onde deixei 4 GB dedicado somente para o JAVA. Voce tem ideia do que pode ser? abaixo segue parametro utilizado deticado a VM.
Atualmente estamos utilizando JDK 1.5 e Tomcat 5. ambos a ultima versao da serie.
Iniciei algums testes com o JDK 1.6 ja o tomcat 5, pois tenho uma aplicacao que ainda nao roda no tomcat 6.
Se tiver ideia do que possa ser ficarei grato.
O sistema e um ERP desenvolvido pela propria empresa, e nao e um sistema muito pequeno. e porte medio.

Agradeco ajuda.
CATALINA_OPTS="-Xmx3840M -XX:MaxPermSize=1280M -XX:+UseParallelGC -XX:ParallelGCThreads=4 -verbose:gc -XX:+AggressiveHeap -XX:+PrintGCDetails -Duser.timezone=America/Sao_Paulo -Duser.language=pt -Duser.country=BR"
JAVA_OPTS="-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled -Dcom.sun.management.jmxremote.port=3464 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"

Juliano D. Carniel (jujo) disse...

Olá Gilmar,

não sei se isso é algum problema de configuração de JVM, parece ser mais um problema da aplicação, algum memory leak, connection leak...

muito difícil de dizer, teria que analisar toda a aplicação. O que posso te sugerir, é verificar a vm, ver se fica muito recurso aberto (thread, jdbc connection). Existem algumas aplicações pra isso.

Valeu.

Alex Kayser disse...

Juliano,
Em uma maquina 32 bits, o máximo de memória que a jvm consegue alocar não é 1,5G?
Alex

Juliano D. Carniel (jujo) disse...

Olá Alex,

numa maquina 32bits o máximo de memória que pode ser endereçada é de 4GB. Lembre-se que em caso de memória os endereços são todos unsigned.
Já se vc está falando de Windows, creio mesmo que o máximo deva chegar em algo como 1,8gb. Mas isso é por restrição do SO.

Valeu, abraço.