Tuning do Garbage Collector da JVM (GC) pode ser uma tarefa assustadora e é sempre associada a alguns tradeoffs. Esta apresentação é baseada em um caso real e pretende explicar como coletar dados e analisar a performance do GC, explorar o que está por dentro das suas diferentes estratégias, abordar seus pontos fortes e fraquezas e clarear
muitas das opções de inicialização para o Hotspot da JVM da Oracle.
7. Objetivos do GC
● reduzir Latência (latency)
○ exemplo 1: tempo de resposta
● aumentar Vazão (throughput)
○ exemplo 2: gastar o menor tempo possivel no GC
● reduzir Footprint
○ exemplo 3: a memória não é infinita
8. Gerência de memória explícita
char *buffer = (char *) malloc(1024 * sizeof
(char));
…
free(buffer);
Suscetível a esses problemas:
● Ponteiro inválido (dangling pointer)
● Vazamento de memória (memory leak)
● Controle manual de desalocação
9. Gerência de memória automática
Responsabilidades do garbage collector (GC):
● alocar memória
● manter objetos referenciados na memória
● desalocar memória de objetos que não são
mais referenciados
● tornar a memória desalocada disponível
para próxima alocação
12. Características do GC Automático
● compacting vs non-compacting
Inicio
Compacting
Non-compacting
13. Conceito de Gerações
A maioria das aplicações têm:
● Objetos de vida curta (efêmeros)
● Raras referências de objetos antigos para
novos objetos
⇒ Separar os objetos em duas gerações:
● Young Generation
● Old Generation
15. Tipos de GC na JVM Oracle
1. Serial Collector
2. Parallel Collector
3. Parallel Compacting Collector
4. Concurrent Mark-Sweep (CMS) Collector
5. Garbage First (G1) a partir do Oracle JDK 7
16. 1. Serial Collector
As duas geracões (young e old):
● Serial (usa só um core)
● Stop-The-World (a aplicação é
pausada)
-XX:+UseSerialGC
20. 1. Serial Collector
Em geral usado em modo “client”
quando:
● não tem multiplos cores / CPUs
● com pouca memória
● pode ter pausas de alguns
minutos no worst-case
-XX:+UseSerialGC
21. 2. Parallel Collector - Young Gen
● Em paralelo (usa múltiplos
cores / CPUs)
● Stop-The-World (a aplicação é
pausada)
Mesma estratégia do que no
Serial Collector, mas em
paralelo
-XX:+UseParallelGC
22. 2. Parallel Collector - Old Gen
● Serial (usa só um core)
● Stop-The-World (a aplicação é
pausada)
Mesma estratégia do que no
Serial Collector
-XX:+UseParallelGC
23. 2. Parallel Collector
Usado quando:
● tem múltiplos cores / CPUs
● pode ter pausas de alguns
minutos no worst-case
Exemplos: cálculos cientificos,
billing, batch processing
Em geral é melhor usar o
Parallel Compacting Collector
(próximo slide)
-XX:+UseParallelGC
Young Gen Old Gen
24. 3. Parallel Compacting Collector
Young Gen:
Parallel (mesma
estratégia do que no
Parallel Collector)
Old Gen:
Parallel
Os dois são Stop-The-
World
-XX:+UseParallelOldGC
Young Gen Old Gen
25. 3. Parallel Compacting Collector
Usado quando:
● tem múltiplos cores / CPUs
● pode ter pausas de alguns segundos no worst-case
● eventualmente vai substituir o Parallel Collector
Não usa quando nenhum proceso pode pausar a máquina
(por exemplo SunRays). Neste caso pode limitar o número
de CPUs usado pelo GC: -XX:ParallelGCThreads=n
-XX:+UseParallelOldGC
26. 4. Concurrent Mark-Sweep (CMS) Collector
-XX:+UseConcMarkSweepGC
Young Gen:
Parallel e Stop-The-World
(mesma estratégia do que
no Parallel Collector)
Old Gen:
Parallel e Concurrent (ao
mesmo tempo do que a
aplicação usando
múltiplos cores / CPUs)Young Gen Old Gen
27. 4. Concurrent Mark-Sweep (CMS) Collector
-XX:+UseConcMarkSweepGC
Old Gen
● Opção para ativar o
Concurrent Mark
incremental:
-XX:+CMSIncrementalMode
● Dá mais tempo de
processamento para a
aplicação quando tem
poucos cores / CPUs (~1
ou 2)
28. 4. Concurrent Mark-Sweep (CMS) Collector
-XX:+UseConcMarkSweepGC
Old Gen
● Não compactador ⇒ fragmentação do Old Gen
● Fragmentação do Old Gen pode resultar em
pausas longas no GC do Young Gen
● Stop-The-World quando falta memória na Old
Gen
29. 4. Concurrent Mark-Sweep (CMS) Collector
● Mais trabalho ⇒ mais overhead
● Precisa de mais memória (pq é concurrent)
● Mas menos latência; o CMS é também chamado de
low-latency collector
Usa quando:
● precisa pausas curtas de GC ⇒ pouca latência
● tem suficiente número de cores / CPUs (ao mínimo 2)
Exemplo: servidores web
-XX:+UseConcMarkSweepGC
30. 5. Garbage First (G1) a partir do Oracle JDK 7
Motivações:
● Reduzir fragmentação
● Tempos de pausa mais previsíveis (-XX:
MaxGCPauseMillis=n)
-XX:+UseG1GC
33. Máquina “client” Máquinas “server”
(CPUs >= 2 && RAM >= 2 GB
&& ! Win_32)
Modo da JVM
(pode forçar com
-client ou -server)
client server
Garbage Collector Serial Collector Parallel Collector
Tamanho inicial do Heap
(-Xmsn)
4 MB 1/64 da memória total, até 1 GB
(mínimo 32 MB)
Tamanho max do Heap
(-Xmxn)
64 MB 1/4 da memória total, até 1 GB
Ergonomics a partir do Oracle JDK 5
35. ● Suite de testes de performance
● Representativo do uso em produção
● Para cada medida, variar apenas um
parâmetro
Dicas para uma boa análise de
performance
36. JMX
Permite a conexão à JVM a distância
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9010
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
38. Arquivos de log
Opções da linha de comando:
● -XX:+PrintGC
● -XX:+PrintGCDetails
○ com mais detalhes
● -XX:+PrintGCTimeStamps
○ com datas absolutas
44. Exemplo, análise
Máquina com 4 CPUs e 1 GB alocado à JVM
● Comportamento da aplicação
● Frequência e tamanho das alocações no
heap (Young Gen)
● Frequência das promoções Young → Old
● Tempo passado no GC (Young e Old Gen)
● Fragmentação do Old Gen
⇒ Encontramos o worst-case do CMS!
48. Exemplo, resumo
● O GC recomendado não é sempre o melhor:
Servidor web ⇒ latência mínima ⇒ CMS?
● Neste caso a funcionamento interno da
aplicação fiz com que o Parallel Compacting
Collector foi muito melhor
● Testa a performance dos varios GCs, mas
entente sua aplicação para poder otimizar!
49. Assuntos mais avançados
● Cada estratégia de GC tem mais parâmetros
para configurar os detalhes
○ -XX:MaxGCPauseMillis=n
○ -XX:GCTimeRatio=n
○ –XX:NewSize=n / –XX:NewRatio=n / –XX:
SurvivorRatio=n
○ –XX:ParallelGCThreads=n
○ –XX:GCTimeRatio=n
● Exige um bom entendimento da aplicação
● Na nossa experiência é raro precisar mudar
essas opções