Automatizando o ajuste de performance no Java

Por Carl Brahms

Por que automatizar o processo de geração de carga e ajuste de performance pode poupar muito tempo e trabalho?

Publicado em setembro de 2008

O ajuste pode ser uma experiência muito difícil e demorada, especialmente para ambientes que exigem a melhor performance. Os benefícios de um bom ajuste são: ambiente mais estável, menos indisponibilidade e melhor performance geral. Se você tem uma equipe interna de ajuste de performance e um ambiente dedicado para isso, você é um privilegiado. Se você é como nós, cujos esforços para ajuste de performance precisam ser espremidos em intervalos de tempo cada vez mais apertados, este artigo mostrará como a automação do processo o torna mais fácil, rápido e abrangente do que fazê-lo “na unha”.

Princípios básicos do ajuste de performance


O ajuste de performance do Java é um processo contínuo e, muitas vezes, longo e frustrante. Raramente o ajuste consegue resolver problemas de performance na primeira. Às vezes você pode encontrar dificuldades para alcançar a performance ideal, não importando quantas máquinas acrescente ou quantas horas gaste experimentando argumentos de memória obscuros. Para produzir a melhor performance, primeiramente é preciso ter metas claras, um projeto bem pensado, uma implementação sólida e, por fim, um ajuste de performance completo.

Comece com metas claras de performance


Antes de dar qualquer passo para otimizar sua performance, é preciso determinar quais são suas metas. Isso se deve ao fato de que o comportamento esperado e o número de usuários, volume de dados e tamanho das solicitações em grande parte determinam que tipo de decisão adotar no ajuste. Cada ambiente é único, e um entendimento claro de quais são os limites dos aplicativos e do ambiente, bem como do nível de performance e carga que você almeja, o ajudarão a definir uma linha quando você estiver em meio ao processo.

Ajuste as configurações do WebLogic Server


Existem literalmente centenas de configurações que você pode ajustar no WebLogic: tamanhos do pool, ajuste do buffer de backlog da conexão, cache, configurações de JDBC e JMS, definição de prioridades com gerenciadores de trabalho, clustering, etc. Como ponto de partida, confira as Principais recomendações de ajuste para o WebLogic Server. (em inglês).

Encontre os gargalos


O problema nem sempre é com as configurações do JVM ou WebLogic. Certifique-se de que as configurações apropriadas do sistema operacional e da rede estejam ajustadas aos requisitos do aplicativo, especialmente se estiver usando UNIX ou Linux. Monitore o I/O de disco do servidor e da rede, além da utilização da CPU com carga. O tamanho dos blocos do banco de dados, tamanho do pool e outras configurações de ajuste de performance específicas de cada fabricante também devem ser examinados se a performance do banco de dados estiver deixando a desejar. Qualquer restrição de recursos subjacente pode causar uma significativa degradação na performance.

Tenha em mente também que o importante é atingir suas metas de performance, e não eliminar todo e qualquer gargalo. Sempre haverá um gargalo ou uma parte mais lenta do sistema, mas o que importa é atingir suas metas e manter seus clientes satisfeitos.

Ajuste o código do seu aplicativo


Pode soar óbvio, mas os aplicativos precisam ser desenvolvidos tendo em vista a performance. Nos ambientes de SOA de hoje, é fácil os aplicativos crescerem a ponto de se tornarem complexos demais, repletos de problemas que afetam a performance. Aplicativos mal desenhados podem ser a causa de gargalos em recursos do sistema, na rede ou no banco de dados. Projete seu aplicativo usando padrões comprovados de performance e mantenha sua simplicidade.

Ajuste sua pilha


Não importa qual seja seu aplicativo, se a pilha for baixa ou você gastar boa parte do tempo coletando lixo, você deve tentar ajustar o tamanho da pilha geral e suas gerações. A performance do aplicativo muitas vezes é auxiliada ou prejudicada significativamente pelo tamanho da pilha disponível.

Descobrir o tamanho certo da pilha para os seus servidores WebLogic é essencial para uma boa performance. Como regra geral de dimensionamento, convém ter metade da pilha livre ao fim de cada coleta de lixo. Ou seja, a pilha deve ter pelo menos o dobro do tamanho de seus objetos ativos.

Talvez a etapa mais básica do ajuste de performance da pilha seja definir o tamanho mínimo e máximo da pilha com valores iguais. Essa recomendação também é relevante para definir o tamanho de New generation no Sun HotSpot ou de Nursery se você estiver usando o Oracle JRockit. Como padrão, o JVM desperdiça recursos ao aumentar e diminuir constantemente o tamanho da pilha.

Não tenha receio de experimentar e tentar definir o tamanho com o maior valor que seu sistema suporta, menos a memória necessária para o sistema operacional e outros aplicativos. Uma pilha maior reduz a freqüência da coleta de lixo, mas pode demorar mais para executar coletas maiores.

O VM sempre usa mais memória do que o tamanho da pilha para lidar com as bibliotecas nativas e o permGen (no caso do Sun HotSpot), portanto tome cuidado para não exceder o tamanho total da RAM física. A memória de paginação do sistema operacional para o disco reduz drasticamente a performance.

Experimente os coletores de lixo

A coleta de lixo é o mecanismo usado para retomar espaço da pilha de objetos que não estão mais sendo usados. Existem vários esquemas de coleta de lixo que variam de JVM para JVM, e todos usam recursos do sistema de maneiras diferentes. Seu trabalho no processo de ajuste é identificar que tipo de esquema de coleta de lixo funciona melhor para seu aplicativo em particular e suas metas de performance. As metas ao escolher um coletor são: minimizar o tempo de pausa da coleta de lixo e melhorar sua taxa de transferência.

Para ver informações sobre como usar os esquemas de coleta de lixo do Jrockit, consulte a seção sobre "Seleção e ajuste de um coletor de lixo". Para obter uma visão detalhada dos esquemas de coleta de lixo disponíveis com o HotSpot VM da Sun, leia Tuning Garbage Collection with the 5.0 Java Virtual Machine (em inglês).

Outras considerações


Existem muitas opções específicas de performance oferecidas pelos JVMs JRockit e Hotspot. A lista de configurações do WebLogic que afetam a performance é quilométrica. O que é mais essencial para um ajuste produtivo é fazer com que desenvolvedores, arquitetos, engenheiros de sistemas, pessoal de teste de controle de qualidade, engenheiros de rede e DBAs trabalhem juntos como uma equipe. Uma participação multidisciplinar no processo de ajuste pode proporcionar agilidade ao trabalho, melhores resultados e redução de custos.

Os benefícios da automação


Agora que já vimos alguns dos aspectos básicos do ajuste de performance do WebLogic, vamos ver como a automação dessas tarefas pode realmente tornar o processo de ajuste de performance mais fácil, menos demorado e mais eficaz.

Mudanças rápidas, ajustes freqüentes


Observei de forma recorrente que a automação do processo de ajuste de performance produz resultados muito melhores do que os obtidos por especialistas sozinhos. Isso se deve principalmente ao fato de que o processo automatizado consegue efetuar mudanças rapidamente e identificar e medir o impacto sobre a performance com mais agilidade e abrangência do que o indivíduo mais “pilhado” conseguiria. E com o ajuste se tornando um processo tranqüilo, você pode fazê-lo em todos os lançamentos de código e acompanhar as mudanças nos aplicativos. Muitos problemas de performance são introduzidos por mudanças pequenas na funcionalidade do aplicativo que ninguém previu que afetariam alguma coisa.

Além disso, muias pessoas assumem erroneamente que o ajuste é opcional, porque seus tempos de resposta atuais são suficientes. É fácil ignorar o fato de que um ajuste adequado aumenta a estabilidade e a longevidade de um servidor. Indisponibilidades podem ser causadas pela falta de ajuste ou pelo ajuste incorreto, e um ambiente ajustado adequadamente opera de forma mais previsível e é mais estável.

Resgata seu tempo e sua performance subutilizada


Muitas vezes deixamos de ajustar nossos servidores com a freqüência ou a abrangência necessária, simplesmente porque o processo é muito demorado. Quando você automatiza o processo, dias de trabalho manual podem ser realizados em uma noite, sem intervenção. O pessoal que passava horas ajustando pode usar seu tempo de maneiras mais produtivas.

A economia financeira com a automação do ajuste de Java aumenta rapidamente quando você passa a ter menos indisponibilidades, melhor performance, utilização apropriada do hardware e fica liberado para trabalhar mais em suas atribuições. Muitas vezes, ganhos de microssegundos em performance nos exigentes ambientes atuais se traduzem em uma significativa economia de recursos.

Aprenda vendo


É interessante ver como mudanças de código e diferentes variáveis de ajuste afetam a performance. A automação do ajuste e da análise lhe permite experimentar uma combinação mais diversificada de configurações e, com a monitoração adequada, você pode ver os resultados lado a lado. É como espiar por cima do ombro de uma equipe de especialistas em performance: você começa a aprender por que determinadas decisões foram feitas, tornando o processo muito instrutivo.

Outra excelente conseqüência é a capacidade de ajustar facilmente seus servidores para cada lançamento de código. Você conta com tranqüilidade, sabendo que não haverá surpresas quando chegar a hora de entrar em produção.

Ajuste automatizado, passo a passo


Nesta seção, você conhecerá o processo do uso do Tune Wizard do Applicare da Arcturus para encontrar as configurações do JVM de melhor performance. Demonstrarei o processo de teste de várias configurações de coleta de lixo.

De forma geral, o Tune Wizard inicia seus testes de carga, monitora os servidores, analisa o comportamento, toma decisões com base em inteligência incorporada, ajusta a configuração e repercute nos servidores. Esse processo é repetido, ajustando automaticamente várias configurações do JVM, do sistema operacional e do WebLogic até encontrar a combinação de melhor desempenho. Veja a seguir uma explicação de cada etapa.

Figura 1

Figura 1: O processo da adaptação automatizada de JVM

Como o ajuste se torna muito fácil com a automação, você pode rapidamente se descobrir querendo fazer o ajuste fino e experimentar. No Tune Wizard, existem várias opções avançadas que lhe dão controle sobre a utilização dos recursos, sobre as quais falarei mais adiante. Como em qualquer processo de ajuste de performance, você precisará conhecer um pouco sobre o comportamento do aplicativo. Se seu aplicativo tiver um tempo de aquecimento ou período inicial de armazenamento em cache, você precisará se certificar de executar a carga por um tempo suficiente para obter resultados precisos.

Escolha as configurações do teste de carga


O Tune Wizard integra-se às ferramentas de geração de carga Apache JMeter, HP Load Runner e The Grinder, e também é capaz de disparar carga gerada de seus próprios aplicativos Java personalizados e scripts de shell. Eu não tinha uma ferramenta de carga instalada nem tinha gerado nenhum script de carga ainda, então usei o JMeter (vem incluso) para gravar um script de teste seguindo estas instruções.

Inicializando o Tune Wizard, especifiquei o script de carga e ele me permite personalizar quantos usuários simular. Selecionei 70 usuários para este teste, pois sei por testes anteriores que é por volta disso que a performance do meu aplicativo começa a se degradar.

Da primeira vez que ajusta seus servidores, você pode não saber quantos usuários seu aplicativo agüenta antes de a performance começar a cair. Se eu não soubesse quantos usuários meu ambiente agüenta, eu poderia usar um recurso chamado determinação de capacidade (Figura 2) antes de adivinhar e comprar mais servidores. A finalidade da determinação de capacidade é encontrar o equilíbrio perfeito de uma boa taxa de transferência, sem exceder os limites de utilização dos recursos. A determinação da capacidade lhe permite definir um número inicial e máximo de usuários para experimentar e, durante o ajuste, a carga será aumentada até que o ponto ideal seja atingido entre a taxa de transferência e a utilização dos recursos.

Figura 2

Figura 2: Automatismo da determinação da capacidade

Escolha as condições do teste


Em seguida, você precisa selecionar o número de amostras de monitoração a colher para cada sessão de ajuste, e o intervalo de tempo entre elas. Como mencionei antes, se seu aplicativo tiver um tempo de aquecimento ou período inicial de armazenamento em cache, você poderá ajustar as configurações aqui para se certificar de que o teste terá duração suficiente para obter uma base precisa. Selecionei 20 amostras por sessão, com intervalo de 60 segundos.

Figura 3

Figura 3: Como os aplicativos variam, você pode ajustar o número de amostras e seu intervalo conforme a necessidade, a fim de conseguir captar uma base precisa

Clique em “Go”


Agora, é só sentar e relaxar. Você pode também programar o ajuste para começar a qualquer hora, para que não precise estar presente se quiser que ele comece tarde da noite. O Tune Wizard experimentará cada uma destas configurações e, quando o ajuste estiver concluído, gerará um relatório com recomendações sobre quais configurações renderam a melhor performance.

Enquanto o servidor está sob carga, o Tune Wizard monitora sua performance e integridade. Isso é feito analisando a taxa de transferência, informações da pilha, utilização da CPU, threads, waiters, filas – basicamente tudo o que você observaria se estivesse executando o teste de carga você mesmo. A freqüência e tempo entre as amostras podem ser definidos e personalizados no início da sessão de ajuste.

Esse é um dos aspectos mais interessantes e valiosos do Tune Wizard e de outros recursos do Applicare. Ele vem com um mecanismo de inteligência artificial que toma decisões inteligentes de ajuste de performance. A base de conhecimentos é construída a partir da experiência combinada de consultores de ajuste de performance, metodologias comprovadas e melhores práticas. Ela é capaz de analisar os dados gerados durante o teste de carga e tomar decisões inteligentes sobre o que ajustar em seguida. Assim que o Tune Wizard tiver chegado à melhor combinação possível, ele finalizará o ajuste.

Posso ficar vendo os gráficos de andamento ao vivo no console do Applicare ou posso esperar até o teste terminar e ver os relatórios. Se você quiser verificar os dados para tirar suas próprias conclusões, há uma extensa lista de relatórios e gráficos mostrando detalhes completos sobre o comportamento de cada configuração.

Os resultados


Aqui eu discuti brevemente os resultados do ajuste, mostrei alguns dos gráficos que o Applicare criou sobre as sessões de ajuste e apresentei algumas recomendações adicionais que foram feitas pelo Applicare. Este não foi um exercício exaustivo de ajuste em hipótese alguma, mas mostra o que o Tune Wizard pode fazer em pouco tempo com um pouco de carga. O processo de ajuste levou 4 horas para ser concluído e experimentou 9 combinações diferentes de configurações, ajustando as configurações de JVM e outras, como threads, JDBC, etc. O Tune Wizard procura áreas da configuração que estão sub ou superdimensionadas e as ajusta adequadamente. Dos parâmetros que forneci ao Tune Wizard para experimentar, o de melhor performance foi:

-Xms512m -Xmx512m -XX:CompileThreshold=8000 -XX:PermSize=48m 
-XX:MaxPermSize=128m  -Xverify:none -XX:NewRatio=3 
-XX:SurvivorRatio=6 -XX:+UseParallelGC


O Applicare tem uma seleção de gráficos para mostrar os resultados do ajuste. Para economizar espaço, vou mostrar os gráficos da taxa de transferência e da pilha, com antes e depois. Você pode ver que a utilização da pilha é mais baixa e os os tempos de pausa das grandes coletas de lixo são menores. Pode ver também que a taxa de transferência xaiu ao mesmo tempo em que ocorreu a grande coleta de lixo, mostrando que nossas configurações iniciais antes do ajuste resultariam em pausas longas durante grandes coletas de lixo.

Figura 4

Figura 4: Este gráfico mostra que a taxa de transferência depois do ajuste (azul) foi melhor do que antes (verde)

Figura 5

Figura 5: Uma comparação da utilização da pilha entre sessões. O resultado final depois do ajuste foi um uso mais baixo da memória

Outras recomendações


O Applicare também detectou problemas no comportamento do tempo de execução do aplicativo e na configuração do servidor. Detectou que o cache do EJB estava configurado inadequadamente e sugeriu o aumento do tamanho do cache.

Além disso, o diagnóstico do Applicare relatou que durante o processo de ajuste, o número de sessões abertas foi alto o suficiente para afetar a performance (mais de 17.000 em alguns casos). Apontou as instâncias em que os segundos de intervalo para invalidação da sessão de alguns dos webapps do meu aplicativo estavam definidos com um valor muito alto e recomendou a reavaliação para evitar manter sessões inativas abertas por muito tempo.

O legal foi que eu não precisei adivinhar ou caçar esses gargalos, pois eles foram apresentados claramente pela ferramenta.

Opções avançadas


O Tune Wizard vem com opções predefinidas para cada um dos JVMs suportados do WebLogic, com o objetivo de encontrar o melhor coletor de lixo para o ambiente, mas também dá a usuários avançados a flexibilidade de experimentar qualquer opção que eles quiserem. Para este teste, experimentei algumas das minhas próprias configurações, e ele achou a de melhor desempenho em apenas algumas horas, me poupando um monte de trabalho.


applicare.jvmparams.param6= -Xmn256m -Xss128k -XX\:+UseConcMarkSweepGC 
-XX\:+UseParNewGC -XX\:SurvivorRatio\=8 -XX\:TargetSurvivorRatio\=90 
-XX\:MaxTenuringThreshold\=3 -Xms512m -Xmx512m -XX:CompileThreshold=8000 
-XX:PermSize=48m  -XX:MaxPermSize=128m  -Xverify:none 
applicare.jvmparams.param5= -Xmn256m -Xss128k -XX\:+UseParallelGC 
-XX\:+UseParallelOldGC -XX\:+UseBiasedLocking -Xms512m -Xmx512m 
-XX:CompileThreshold=8000 -XX:PermSize=48m  -XX:MaxPermSize=128m  
-Xverify:none applicare.jvmparams.param4= -Xmn256m -Xss128k 
-XX\:+UseParallelGC -XX\:+UseParallelOldGC -Xms512m -Xmx512m 
-XX:CompileThreshold=8000 -XX:PermSize=48m  -XX:MaxPermSize=128m  
-Xverify:none applicare.jvmparams.param3= -XX\:NewRatio\=3 
-XX\:SurvivorRatio\=6 -XX\:+UseConcMarkSweepGC -Xms512m -Xmx512m 
-XX:CompileThreshold=8000 -XX:PermSize=48m  -XX:MaxPermSize=128m  
-Xverify:none applicare.jvmparams.param2=-XX\:NewRatio\=3 
-XX\:SurvivorRatio\=6 -XX\:+UseParallelGC -Xms512m -Xmx512m 
-XX:CompileThreshold=8000 -XX:PermSize=48m  -XX:MaxPermSize=128m  
-Xverify:none applicare.jvmparams.param1=-XX\:+UseParallelGC 
-XX\:MaxGCPauseMillis\=3 -Xms512m -Xmx512m -XX:CompileThreshold=8000 
-XX:PermSize=48m  -XX:MaxPermSize=128m  -Xverify:none

Você também pode configurar o quanto de CPU quer utilizar durante a execução do ajuste de determinação de capacidade. Muitas vezes acontece de você estar compartilhando a mesma máquina entre vários servidores gerenciados, portanto naturalmente você deve querer limitar o espaço do hardware para cada processo sob carga. Limites para o comprimento aceitável da fila, número de waiters e outras opções configuráveis lhe dão a capacidade de adaptar a ferramenta às necessidades exclusivas do seu ambiente.

Conclusão


O processo de ajuste do WebLogic permanece o mesmo – exceto pelo fato de que o tedioso trabalho de executar cargas, analisar performance, fazer mudanças apropriadas e reiniciar o servidor WebLogic passa a ser todo automático. O Tune Wizard atua como ferramenta para automação da geração de carga e ajuste de performance.

Abordei os recursos automatizados de ajuste do JVM neste artigo, mas o Applicare também automatiza a análise da configuração, detecção de problemas e detecção de causa-raiz, oferecendo diversos outros recursos voltados para a melhora da performance e da disponibilidade.

Referências




Carl Brahms
é engenheiro sênior da Arcturus Technologies Inc.