Otimização de Desempenho em Java: Oito Antipadrões que Desaceleram seu Código

Melhorias de Desempenho ao Corrigir Antipadrões
Jonathan Vogel construiu um aplicativo Java de processamento de pedidos que inicialmente tinha 1.198ms de tempo decorrido, processava 85.000 pedidos por segundo, usava pouco mais de 1GB de heap e tinha 19 pausas de GC. Após corrigir oito antipadrões sem alterações arquiteturais ou atualizações do JDK, o desempenho melhorou para 239ms de tempo decorrido, 419.000 pedidos por segundo, 139MB de heap e 4 pausas de GC. Isso representa 5x mais throughput, 87% menos uso de heap e 79% menos pausas de GC.
Oito Antipadrões de Desempenho Java para Corrigir
- Concatenação de strings em loops - cópia O(n²) devido à imutabilidade
- Iteração O(n²) de streams dentro de loops - percorrendo a lista completa por elemento
- String.format() em caminhos críticos - construtor de strings mais lento, analisa o formato a cada chamada
- Autoboxing em caminhos críticos - milhões de objetos wrapper descartáveis
- Exceções para fluxo de controle - fillInStackTrace() percorre toda a pilha de chamadas
- Sincronização muito ampla - um bloqueio se torna o gargalo
- Recriar objetos reutilizáveis - ObjectMapper, DateTimeFormatter, Gson por chamada
- Fixação de threads virtuais (JDK 21-23) - synchronized + I/O bloqueante fixa os carriers
Exemplos e Correções Detalhadas
1. Concatenação de Strings em Loops
Código problemático:
String report = "";
for (String line : logLines) {
report = report + line + "\n";
}Isso cria cópia O(n²) devido à imutabilidade de String. Benchmarks BellSoft JMH mostram que quando n cresce 4x, a concatenação em loop fica mais de 7x mais lenta.
Correção:
StringBuilder sb = new StringBuilder();
for (String line : logLines) {
sb.append(line).append("\n");
}
String report = sb.toString();Nota: Desde o JDK 9, o compilador otimiza concatenação de linha única como "Pedido: " + id + " total: " + amount, mas essa otimização não se aplica a loops.
2. O(n²) Acidental com Streams Dentro de Loops
Código problemático:
for (Order order : orders) {
int hour = order.timestamp().atZone(ZoneId.systemDefault()).getHour();
long countForHour = orders.stream()
.filter(o -> o.timestamp().atZone(ZoneId.systemDefault()).getHour() == hour)
.count();
ordersByHour.put(hour, countForHour);
}Esse padrão representou quase 71% das amostras de pilha de CPU na gravação JFR. Com 10.000 pedidos, ele realiza 100 milhões de comparações em vez de uma única passagem.
Correção:
for (Order order : orders) {
int hour = order.timestamp().atZone(ZoneId.systemDefault()).getHour();
ordersByHour.merge(hour, 1L, Long::sum);
}Isso fornece desempenho O(n) com uma passagem. Você também poderia usar Collectors.groupingBy(... Collectors.counting()) em um único pipeline de stream.
O artigo é a parte 1 de uma série de 3 partes sobre Otimização de Desempenho Java, com as partes 2 e 3 em breve. A parte 2 analisará os dados de perfilamento por trás desses números, incluindo flame graphs e quais métodos eram realmente críticos.
📖 Read the full source: HN AI Agents
👀 See Also

Configurando o Qwen3.5-27B Localmente: Comparação entre vLLM e llama.cpp
Um usuário do Reddit compartilha dicas práticas para executar o Qwen3.5-27B localmente, comparando os backends llama.cpp e vLLM com recomendações de configuração específicas e resultados de benchmark.

Desenvolvedor de iOS Compartilha Melhores Práticas de Código Claude Após Lançar Múltiplos Aplicativos
Um desenvolvedor iOS com experiência em cibersegurança descreve práticas específicas para usar o Claude Code de forma eficaz, incluindo separação de ambientes, configuração de observabilidade e evitar o acúmulo de dívida técnica.

Avaliando a Segurança das Habilidades do Agente: Considerações-Chave Antes da Instalação
Instalar novas habilidades de agentes pode melhorar a funcionalidade, mas também traz riscos. Aprenda como avaliar a segurança dessas habilidades para proteger seu sistema.

Otimizando o AutoResearch no RTX 5090: O que falhou e o que funcionou
Um desenvolvedor compartilha detalhes específicos de configuração para executar o AutoResearch em uma configuração RTX 5090/Blackwell, incluindo abordagens que falharam e pareciam funcionais, mas tiveram desempenho ruim, e a configuração funcional que alcançou resultados estáveis com TOTAL_BATCH_SIZE=2**17 e TIME_BUDGET=1200.