Guia Boas Práticas em Java

Garbage Collection: Entendendo e otimizando - Parte 2

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (0)  (0)

O artigo apresenta o funcionamento dos collectors das JVMs Oracle JRockit, IBM Virtual Machine for Java, as que implementam a JSR-1 e Dalvik.

Artigo no estilo Curso

De que se trata o artigo:

O artigo trata de apresentar o funcionamento dos collectors das JVMs Oracle JRockit (utilizada pelo servidor de aplicações Java EE WebLogic), IBM Virtual Machine for Java (utilizada pelo servidor de aplicações Java EE WebSphere), as que implementam a JSR-1 (também conhecida como Real-Time Specification for Java ou RTSJ) e Dalvik (utilizada por dispositivos Android).

Em que situação o tema útil:

O tema é muito pertinente a desenvolvedores Java que trabalham com alguma das JVMs mencionadas acima, para entender mais a fundo as consequências da utilização de collectors frente a cenários particulares. Além disso, desenvolvedores Java que não trabalham com alguma destas JVMs poderão aprender como que estas opções solucionam os mesmos problemas de Garbage Collection que a JVM HotSpot de maneira diferente, acrescentando à sua bagagem de conhecimento.

Resumo DevMan:

O artigo começa apresentando a JVM Oracle JRockit e suas configurações de memória heap, seus collectors e como utilizá-los. Em seguida, apresenta também a JVM IBM Virtual Machine for Java, suas configurações de memória heap, seus collectors e como utilizá-los. A partir daqui, apresenta a especificação JSR-1 e seus conceitos com relação ao desenvolvimento de aplicações de tempo real em Java, e demonstra o funcionamento de 5 collectors de tempo real. Ainda, apresenta a JVM Dalvik e seus desafios com relação a Garbage Collection, além de seu collector e melhorias com respeito ao gerenciamento de memória.

No artigo anterior da série “Entendendo e otimizando o Garbage Collection”, foram explicados fundamentos e detalhes sobre o processo de Garbage Collection em Java e o funcionamento dos collectors da JVM HotSpot 6 e 7. Além disso, foi apresentado como otimizar seu comportamento por meio de opções da JVM.

Apesar da maior parte dos desenvolvedores utilizar a JVM HotSpot, há outras JVMs no mercado que também sofrem dos mesmos problemas relacionados com Garbage Collection anteriormente apresentados. Estas JVMs apresentam diferentes interpretações para certos problemas, surgindo assim soluções criativas para cenários particulares.

A intenção deste artigo é dar continuidade a este estudo, agora abordando JVMs como Oracle JRockit (utilizada pelo servidor de aplicações Java EE WebLogic), IBM Virtual Machine for Java (utilizada pelo servidor de aplicações Java EE WebSphere), a especificação JSR-1 (também conhecida como Real-Time Specification for Java ou RTSJ) e finalmente a JVM Dalvik (utilizada por dispositivos Android).

Collectors daJVM JRockit (WebLogic)

A JVM Oracle JRockit, projetada especialmente para o servidor de aplicações Java EE WebLogic, é uma JVM comercial considerada de alta performance. Atualmente, ela está sendo integrada com a JVM HotSpot para o lançamento de uma nova JVM, possivelmente no JDK 8. Com relação a Garbage Collection, funciona de maneira um pouco diferente que a HotSpot.

Garbage collector dinâmico

A JVM JRockit possui um modo de Garbage Collection dinâmico, que combinará heurísticas e otimizará a performance de acordo com as necessidades da aplicação. A partir da definição do perfil do collector, a sua escolha acontecerá em tempo de execução, de forma parecida com Ergonomics da JVM HotSpot.

Este modo pode ser explicitamente escolhido utilizando a opção da JVM: -XgcPrio:<perfilDoCollector>, onde perfilDoCollector pode ser:

· throughput: otimização para maximização do throughput da aplicação;

· pausetime: otimização para a minimização do tempo de pausa;

· deterministic: otimização para tempos de pausa muito curtos e determinísticos.

Funcionamento geral

A JVM JRockit possui duas configurações possíveis da memória heap. A primeira delas é generacional, assim como na HotSpot, sendo dividida conforme a Figura 1, obtida do blog about:performance.

Figura 1. Gerações da memória heap na JVM JRockit.

Aqui, a Young generation é chamada de Nursery, sendo subdividida em duas áreas: Keep Area, que não sofre collections e recebe os objetos após serem alocados; e a área remanescente, onde todos os seus objetos podem ser promovidos para Tenured, diferentemente dos espaços Survivor da HotSpot. JRockit promove um objeto para Tenured quando ele sobrevive a duas Minor collections. Por ser generacional, esta configuração busca fornecer tempo de pausa baixo.

Não há Permanent generation em JRockit. Todas as classes, strings e constantes são alocadas em Young ou Tenured generation. Por um lado, fica mais fácil de configurar e há mais memória para as outras generations; mas por outro lado, classes, strings e constantes podem ser coletadas quando não usadas novamente, o que pode introduzir problemas de performance.

Além disso, há a configuração de memória heap contínua, não classificando objetos por seu tempo de vida. Em certas situações, como tarefas em lote que prezam por alto throughput, esta configuração apresenta melhor performance.

A configuração contínua vem configurada para ser utilizada como padrão, o que não é ideal, pois a maioria das aplicações é fortemente baseada em arquitetura Web, onde há muitos objetos que sobrevivem por pouco tempo, sendo assim mais vantajoso utilizar uma configuração de memória heap generacional, para obter tempos de pausa mais baixos que na configuração de memória heap contínua.

A JVM JRockit possui collectors Parallel e Concurrent assim como a HotSpot, mas aqui cada um destes pode ser utilizado com a configuração de memória heap generacional ou contínua, a partir da versão R27.2. Estes collectors são abordados a seguir.

Parallel em memória heap contínua

O collector Parallel não apresenta grandes diferenças quanto ao seu homônimo da JVM HotSpot. Quando configurado em memória heap contínua, seu processo de collection é feito com a pausa de todas as threads Java e então a execução de diversas threads paralelas para realizar collections completas em toda a memória heap.

Assim como em HotSpot, preza por alto throughput ao invés de baixo tempo de pausa. Além disso, é mais adequado para aplicações que mantêm objetos na memória por muito tempo.

Este collector pode ser explicitamente escolhido utilizando a opção da JVM: -Xgc:singlepar.

Parallel em memória heap generacional

Na memória heap generacional, novos objetos são primeiramente alocados na generation Nursery, até esta ficar cheia. Quando isto acontece, o collector Parallel pausa todas as threads Java para uma minor collection paralela em Nursery, utilizando diversas threads. O mesmo acontece com a generation Tenured, porém aqui ocorre uma major collection.

Assim como em HotSpot, preza por alto throughput ao invés de baixo tempo de pausa. Além disso, é mais adequado para aplicações que alocam muitos objetos que sobrevivem por pouco tempo, visto que as collections durarão menos, conseguindo assim melhorar o tempo de pausa.

Este collector pode ser explicitamente escolhido utilizando a opção da JVM: -Xgc:genpar.

Mostly Concurrent em memória heap contínua

O collector Mostly Concurrent da JVM JRockit apresenta algumas diferenças importantes com relação ao collector Concurrent da JVM HotSpot, como a sua divisão de fases, que são:

· Marcação inicial: todas as threads da aplicação são suspensas para a marcação do primeiro nível de objetos alcançáveis a partir das raízes (objetos diretamente acessíveis pela memória heap);

· Marcação concorrente: as threads da aplicação são retomadas, e inicia-se concorrentemente o processo de navegação e marcação dos objetos alcançáveis pelos objetos marcados na etapa anterior. Não é garantido que todos os objetos alcançáveis da memória heap serão marcados nesta etapa, pois uma vez que este processo é concorrente com a aplicação, novos objetos podem ter sido criados a partir de objetos que já foram visitados desde o início desta etapa, e assim acabam ficando sem serem marcados como alcançáveis;

· Pré-limpeza: as threads da aplicação continuam em execução, todas as mudanças na memória heap durante a fase de Marcação concorrente são identificadas e todos os novos objetos alcançáveis são marcados;

· Marcação final: todas as threads da aplicação são suspensas novamente, todas as mudanças na memória heap durante a fase de Pré-limpeza são identificadas e todos os novos objetos alcançáveis são marcados;

· Sweeping em concorrência: as threads da aplicação são retomadas, e inicia-se concorrentemente o processo de sweeping da memória heap, mas diferentemente da JVM HotSpot, ocorre em duas etapas. Inicialmente o sweeping é feito na primeira metade da memória heap, e quando isto acontece, novos objetos só podem ser alocados na segunda metade. Após uma curta pausa para sincronização, acontece o sweeping na segunda metade, seguida por outra curta pausa para sincronização.

No geral, o collector Mostly Concurrent da JVM JRockit realiza mais pausas que o Concurrent da JVM HotSpot, porém suas fases de remarcação são mais curtas.

Na memória heap contínua, realiza a maioria de seu trabalho concorrentemente com a aplicação Java. Assim como em HotSpot, preza por baixo tempo de pausa ao invés de alto throughput. Além disso, é mais adequado para aplicações que mantêm objetos na memória por muito tempo.

Este collector pode ser explicitamente escolhido utilizando a opção da JVM: -Xgc:singlecon.

Concurrent em memória heap generacional

Na memória heap "

A exibição deste artigo foi interrompida :(
Este post está disponível para assinantes MVP

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Ficou com alguma dúvida?