12

Click here to load reader

Performance de Aplicações Java

Embed Size (px)

Citation preview

Page 1: Performance de Aplicações Java

Especificação de Integração

Performance de Aplicações Java

Tuning de JVM1.0

Página 1 de 11

Page 2: Performance de Aplicações Java

Tuning de JVM

Página 2 de 11

Page 3: Performance de Aplicações Java

Tuning de JVM

Índice

Apresentação 4

1. Introdução 4

2. Público Alvo 4

3. Quando utilizar este documento? 4

Parte I – Memória e Garbage Collection 5

4. Memória do Processo JVM 5

4.1.1 Modelo de Memória da JVM 5

5. Garbage Collection 6

5.1.1 Alocação e execução do garbage collection 65.1.2 Dimensões da Memória Heap 65.1.3 Dimensões da Memória Non-Heap (Permanent Generation) 7

Parte II – Ferramentas de Monitoramento 9

6. JConsole 9

6.1.1 Executando o JConsole 96.1.2 Overview de Processamento e Memória 106.1.3 Análise de Memória Heap e Non-Heap 116.1.4 Obter Informações da JVM 11

Página 3 de 11

Page 4: Performance de Aplicações Java

Tuning de JVM

1. Apresentação

2. IntroduçãoO objetivo deste documento é fornecer informações básicas de como a Java Virtual Machine

fornecida pela Sun Microsystems organiza seu modelo de memória, como esta memória pode ser monitorada e quais ferramentas, e como poderemos modificar a organização de tal memória para prover um ganho de performance para a aplicação.

3. Público AlvoEste documento tem como público alvo administradores de infraestrutura, arquitetos e

desenvolvedores de aplicação que rodam na plataforma Java.

4. Quando utilizar este documento?Este documento deve ser consultado sempre que houver implantação de aplicações em novos

ambientes ou quando aplicações sofrerem problemas de performance.

Página 4 de 11

Page 5: Performance de Aplicações Java

Tuning de JVM

Parte I – Memória e Garbage Collection

5. Memória do Processo JVMA Sun foi o primeiro fornecedor da JVM, cuja implementação é a mais utilizada. Também temos

outros fornecedores tais como a IBM e Oracle (Bea - JRockit). A JVM da Sun opera sob a premissa que objetos de curta duração de vida são criados e destruídos muito rapidamente. Para gerenciar a forma de alocação dos objetos a Sun implementou o heap no que foi chamado de gerações, Young Generation e Old Generation, conforme apresentado no tópico seguinte.

5.1.1 Modelo de Memória da JVM

Mem

óri

a He

ap Yo

un

g G

ener

atio

n Éden – Área onde são criado os objetos novos.

Survivor Space 0 (From)

Survivor Space 1 (To)

Old

Gen

era

tio

n Tenured Space

Non-Heap

Code CachePermanent Shared-RWPermanent Shared-ROPermanent

Figura 1

Conforme apresentado acima a JVM fornecida pela Sun divide o heap em duas partes: Old Generation (Tenured Space), e Young Space (New Space). Observe que a geração Young é dividida em três partes: O Éden e duas Survivos Spaces, chamadas de From Space e To Space. Objetos são criados no Éden; quando o Éden está cheio, objetos ainda em uso são copiados para o From Space; Quando o Éden fica cheio novamente, os objetos no From Space são copiados para o To Space; e finalmente; se os objetos continuam em uso quando o Éden fica cheio novamente, então os mesmos são movidos para a Old Generation (Tenured Space). A imagem abaixo, figura 2, apresenta como os objetos são movidos no heap a cada momento que o Éden fica cheio.

Figura 2 (Fonte da Figura: Internet)

Página 5 de 11

Page 6: Performance de Aplicações Java

Tuning de JVM

6. Garbage CollectionO parágrafo anterior descreveu o resumo de como os objetos são alocados no heap, para fixar o

entendimento segue novamente abaixo todo o processo de maneira um pouco mais detalhada.

Atenção: Não confundir Garbage Collector com garbage collection. O garbage Collector é quem executa o Garbage Collection.

6.1.1 Alocação e execução do garbage collection

Os objetos Java são criados no Éden Space, dentro da geração Young. Quando são criados objetos suficientes para preencher o Éden, então o Garbage Collector executa uma pequena garbage collection, as vezes chamada de “Copy Collection”. Neste pequeno garbage collection, o Garbage Collector examina os objetos do Éden: removendo todos os objetos sem referência e copiando os objetos em uso para o From Space até que o From Space fique cheio. Desta forma, objetos de vida curta irão “morrer” no Éden, enquanto que os objetos “sobreviventes” serão movidos para o From Space; com isso estamos liberando, pelo menos, o número de bytes que compõem o conteúdo do Éden referente ao tamanho do From Space.

Quando o Éden fica cheio novamente, objetos em uso no From Space são copiados do From Space para o To Space, em teoria. Na pratica a JVM mantém um ponteiro para os Survivo Spaces e a cada vez que um pequeno garbage collection executa, a JVM simplesmente altera os ponteiros, do From Space para o To Space.

Quando o Éden novamente fica cheio, então quaisquer objetos que ainda estão em uso no To Space são retirados para a geração Old (Tenured Space). Estes pequenos garbage collections são muito rápidos e eficientes, geralmente variam de décimos de segundo a centésimos de segundo, a depender do tamanho do heap, e das threads da JVM não serem interrompidas durante estes garbage collections.

Quando a geração Young (Éden e Survivos) estão cheios, e o Garbage Collector precisa de memória livre, então é executado um garbage collection maior (Full Garbage Collection). Este garbage collection congela todas as threads que estão rodando na JVM e executa o teste de acessibilidade. O teste de acessibilidades resulta na marcação dos objetos em uso no heap, que logo são seguidos por uma varredura de objetos mortos e uma compactação opcional para liberar espaço no heap. Garbage collection conhecido também como “Mark-and-sweep collection”, este tipo de garbage collection executa operações extremamente intensivas de processamento e pode variar no tempo de alguns décimos de segundo para vários segundos; Há casso em que pode durar até 20 segundos.

Portanto, independente de como você bem tune a JVM para sua aplicação ganhar performance, freqüentemente maiores garbage collections poderão afetar a performance da aplicação.

A esperança da estratégicas de gerações é que movendo objetos na geração Young Generation, objetos de vida curta podem morrer e liberar memória livre, antes de ser movido para a geração Old (Tenured Space). Geralmente durante todo o tempo, objetos de longa duração irão permanecer na geração Old, enquanto que objetos de curta duração irão morrer na geração Young, durante pequenos garbage collection..

6.1.2 Dimensões da Memória Heap

As dimensões dos retângulos da figura 1, com relação às gerações Young e Old, foram propositalmente ajustadas afim de sugerir como que o tamanho de cada área do heap é comumente dimensionado nas atividades de tuning de JVM. Em muitas situações poderá ser observado melhor performance com as seguintes dimensões: A geração Young um pouco menor que a metade do heap, e cada Survivo Space cerca de 1/8 da geração Young. Infelizmente, por causa do fato da JVM ser projetada para uma grande variedade de tipos de aplicações, a configuração padrão costuma ser longe da ideal para aplicações empresariais que suportam centenas de usuários simultaneamente.

Página 6 de 11

Page 7: Performance de Aplicações Java

Tuning de JVM

A configuração padrão varia de acordo com o sistema operacional, mas em geral, a geração Young Generational é muito pequena, 32MB ou 64MB, e os Survivo Spaces são somente 1/34 da geração Young, o que costuma estar entre um pouco menos que 1MB e 2MB. O problema é quando vários usuários acessam a aplicação simultaneamente, causando a carga de vários objetos em memória, muitos destes objetos que são de vida curta acabam prematuramente sendo carregado na geração Old, e requer que um maior garbage collection seja necessário para coletá-los. Esta carga prematura na geração Old, entra em conflito com a estratégica inicial do garbage collection. Lembre-se que quando Eden está cheio, o mesmo não é liberado de uma só vez, mas em pedaços, pelo menos, o tamanho do espaço de um Survivor Space. Portanto, mesmo que tenhamos um heap de 2GB, haverá de ser executado um garbage collection, todo o tempo, para cada megabyte (tamanho do Survivor Space) que é criado.

Quando a JVM é iniciada, você pode redimensionar a geração Young, bem como Éden e os tamanhos dos Survivor Spaces. Conforme havia informado, a preferência de muitos administradores de sistemas, para tuning de JVM fornecido pela Sun, é dimensionar a geração Young um pouco menos de metade do tamanho do heap, mas não muito menor. De acordo com a especificação JVM, tornando a geração Young superior a metade do heap a capacidade de executar um pequeno garbage collection (copy collection) fica comprometida, resultando em uma mark-and-sweep (marca-e-varrer) para pequenos garbage collections.

Segue abaixo tabela de parâmetros para definição dos tamanhos das principais áreas do heap.

Parâmetro Descrição-XmxNNNm Tamanho máximo do heap, onde NNN representa o tamanho do

heap e m representa a unidade (m=megabytes ou g=gigabytes)-XmsNNNm Tamanho mínimo do heap. Geralmente inicio com o mesmo

tamanho máximo do heap.-XX:MaxNewSize=NNNm Tamanho máximo da geração Young.-XX:NewSize=NNNm Tamanho mínimo da geração Young.-XX:SurvivorRatio=n Tamanho dos Survivor Spaces, onde n é a relação com tamanho

da geração Young (*). (*) O tamanho do Survivor Space é definido da seguinte forma, o Éden recebe um numero de

unidades especificado pelo SurvivorRatio, enquanto cada Survivor Space recebe uma unidade, por exemplo, se SurvivorRatio receber o valor 6, o Édem terá um tamanho de 6/8 da geração Young enquanto que cada Survivor Space tará o tamanho de 1/8 da geração Young. Quando NewSize e MaxNewSize forem iguais poderemos aplicar as seguintes fórmulas.

Éden = ((n – 2) / (n + 2)) * NewSize

Cada Survivor Space = (1 / (n + 2)) * NewSize

Onde n é o valor do SurvivorRatio.

Segue abaixo alguns exemplos recomendados para configurar heap de 1GB e 2GB.

-Xmx1024m -Xms1024m -XX:MaxNewSize=448m -XX:NewSize=448m -XX:SurvivorRatio=6

-Xmx2048m -Xms2048m -XX:MaxNewSize=896m -XX:NewSize=896m -XX:SurvivorRatio=6

6.1.3 Dimensões da Memória Non-Heap (Permanent Generation)

Após a configuração do heap, deve-se configurar a região conhecida como “non-heap”, ou Permanent Space. A Permanent Space faz parte do conjunto de memória utilizada pelo processo da JVM, porém a mesma não impacta no tamanho do heap, por exemplo, a memória que você solicita para o Permanent Space não utiliza a memória separada para o heap via parâmetro –XmxNNN. O heap contém instâncias de objetos, mas antes de criar os objetos a JVM precisa primeiro abrir os arquivos das classes e carregar o bytecode. Quando a JVM ler o bytecode, ela o armazena na memória Permanent Space (Permanent Generation). Após carregadas na memória estas classes podem então serem usadas para criar instâncias de objetos no heap, cuja referência são retornadas ao código chamador.

Página 7 de 11

Page 8: Performance de Aplicações Java

Tuning de JVM

A Permanent Space não deve ser ignorada, porque você precisa memória suficiente para alocar todas as classes de sua aplicação, isso inclui os arquivos JSP, devido ao fato dos arquivos JSP serem traduzidos para Servlets e compilados em classes Java, e por conseqüência serem carregadas na Perment Space, relacionada a memória do processo JVM em execução. Se sua aplicação usa muitos arquivos JSP, você talvez tenha de aumentar o tamanho da Permanent Space. Lembre que uma Permanent Space pequena faz com que o processo da JVM tenha de acessar com mais freqüência o disco rígido para carregar as classes, impactando a performance do processo.

Segue abaixo os parâmetros de inicialização da JVM para dimensionar a Permanent Space.

Parâmetro Descrição-XX:MaxPermSize Tamanho máximo da Permanent Space, onde NNN representa o

tamanho e m representa a unidade (m=megabytes ou g=gigabytes)

-XX:PermSize=NNNm Tamanho mínimo da Permanent Space.

Página 8 de 11

Page 9: Performance de Aplicações Java

Tuning de JVM

Parte II – Ferramentas de Monitoramento

7. JConsoleO JConsole é uma ferramenta que acompanha o Java 2 Platform Standard Edition (J2SE), sua

finalidade é monitorar aplicações para fins de gerenciamento e suporte. O JConsole não só fornece interface para gerenciamento da JVM local, mas também prover suporte a monitoramento e gerenciamento remoto. Através da tecnologia JMX, o JConsole executa extensiva instrumentação da JVM, e prover suas informações de performance, bem como consumo de recursos pelas aplicações.

Atenção: Apesar de ser uma ótima ferramenta, infelizmente o JConsole não permite acompanhar o comportamento da memória junto com o gráfico de comportamento do garbage collection. Para isso iremos apresentar o VisualGC.

7.1.1 Executando o JConsole

O JConsole, assim como as demais ferramentas que acompanham o JDK encontra-se instalado na pasta Bin, conforme imagem abaixo.

Após executá-lo será apresentado a tela de seleção de processo e login (quando remoto). Observe que os processos não compatíveis para gerenciamento encontram-se desabilitados para seleção, é o caso do OC4J (PID 212).

Página 9 de 11

Page 10: Performance de Aplicações Java

Tuning de JVM

7.1.2 Overview de Processamento e Memória

Ao entrar no JConsole é apresentado a tela abaixo. Observe que nesta tela inicial já temos uma gama de informações, que mesmo não sendo detalhadas já podem ajudar em nosso Tuning.

Heap Memory Usage – Por meio deste gráfico podemos analisar se os valores de xms e xmx estão suficientes para aplicação.

Threads – A quantidade de threads simultâneas nos ajudar a identificar se a aplicação precisa de refactoring para utilização de ThreadPool, com processamento de grupos em grupos de threads, evitando com isso a escassez total dos recursos.

Classes – Através da quantidade de classes podemos estimar “uma idéia” o tamanho da Permanent Space.

CPU Usage – Nos apresenta se os recursos de processamento estão suficientes para a aplicação. Caso a memória e a aplicação estejam ok, talvez seja necessário um upgrade do processador.

Página 10 de

11

Page 11: Performance de Aplicações Java

Tuning de JVM

7.1.3 Análise de Memória Heap e Non-Heap

Acredito que esta aba contenha as principais informações para tuning da JVM. Com ela poderemo investigar todas as áreas do heap e non-heap, nos ajudando a estimar os corretos valores para as gerações Young, Old e Permanent. Para alternar entre os gráficos das diferenets áreas de memória basta executar um clique no retângulo verde-claro referente a área de memória desejada.

7.1.4 Obter Informações da JVM

O JConsole também fornece diversas informações sobre o processo da JVM em análise. Com ele poderemos investigar quais parâmetros foram passados (se foram!) para tuning do processo, bem como recursos de hardware, sistema operacional e garbage collection.

Página 11 de

11