Java: aceleração de código com profiling e otimização

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Desempenho Java: de "lentidão" a resposta reativa



Você já iniciou sua aplicação Java e ela "pensou" por um segundo ou dois, como se decidindo se valia a pena atendê-lo? Ou talvez seu servidor começou a sufocar sob carga, e a CPU foi a 100%? Familiar? Bem-vindo ao mundo do desempenho Java — um lugar onde até o código mais elegante pode se transformar em um monstro lento. Mas não se apresse em culpar a linguagem. Na maioria das vezes, o problema não está no Java, mas em como o usamos.



Neste artigo, não vamos ler palestras chatas. Vamos pegar um código real e "lento", executá-lo através de um profiler, encontrar o gargalo e aplicar a otimização Java de modo que a aplicação decole. Pronto? Vamos lá!



Por que as aplicações Java são lentas? (E qual a participação do Garbage Collector)



Antes de pegar as ferramentas, vamos entender os principais inimigos da velocidade:



  • Garbage Collector (GC) — amigo ou inimigo? Ele libera memória, mas se você cria milhões de objetos por segundo, o GC trabalhará como um louco, consumindo recursos da CPU. Isso é chamado de GC pauses.
  • Estruturas de dados incorretas. Usar LinkedList onde é necessário ArrayList é como dirigir um tanque em uma pista de corrida.
  • Bloqueios (Locks). Sincronização é uma faca de dois gumes. Sem ela — caos, com ela — potenciais engarrafamentos.
  • Cálculos redundantes. Por que calcular a mesma coisa cem vezes se pode fazer uma vez?


Mas como encontrar o culpado específico? É aqui que entra o profiling Java.



Profiling Java: seu detetive particular



Profiling é como um raio-X para o seu código. Você vê quais métodos são chamados com mais frequência, quanto tempo eles levam e quantos objetos são criados. Sem isso, qualquer otimização é um palpite no escuro.



Ferramentas de profiling: das gratuitas às profissionais



  • VisualVM — gratuito e vem com o JDK. Ótimo para análise rápida de CPU e memória.
  • JProfiler — poderoso, pago, mas com versão de teste. Fornece relatórios detalhados sobre threads, GC e consultas SQL.
  • Java Flight Recorder (JFR) — embutido na HotSpot JVM. Impacto mínimo no desempenho.
  • Async Profiler — open-source, opera no nível do kernel, quase não desacelera a aplicação.


Para nosso exemplo, usaremos o VisualVM — é simples e intuitivo.



Exemplo prático: encontrando o problema



Imagine que temos um método que processa uma lista de pedidos e os converte para XML. O código funciona, mas para 10.000 pedidos — é terrivelmente lento. Aqui está ele:



public String generateXmlReport(List<Order> orders) {    StringBuilder sb = new StringBuilder();    sb.append("<orders>");    for (Order order : orders) {        // Problema: concatenação de strings no loop!        sb.append("  <order id=\\"" + order.getId() + "\\">");        sb.append("    <amount>" + order.getAmount() + "</amount>");        sb.append("  </order>");    }    sb.append("</orders>");    return sb.toString();}


Iniciamos o VisualVM, conectamos à aplicação, clicamos em "CPU Profiler" e disparamos nosso método. Após alguns segundos, vemos o cenário: o método generateXmlReport ocupa 80% do tempo da CPU! E dentro dele — o método StringBuilder.append e… espere… StringBuilder.toString é chamado a cada iteração? Não, é apenas a concatenação com + que cria um novo StringBuilder e String a cada vez. Horror!



Conclusão do profiler: o problema está na concatenação de strings dentro do loop

Blogs

Book Recommendations