Debugando gargalos de performance em um sistema Java legado
Bom dia, pessoal! 👋
Gostaria de compartilhar uma situação que aconteceu comigo ontem.
Presto serviço terceirizado para um órgão do governo do meu estado, dando suporte a diversos sistemas — principalmente almoxarifado e patrimônio.
Ontem, fui acionado para apoiar um problema no fluxo de doação. O sistema em questão é antigo (cerca de 10 anos), desenvolvido em Java 6, com JSP no front. Tudo bem acoplado e… do jeitinho certo para dar dor de cabeça 😅. O código é bem legado, cheio de boilerplate, o que acaba trazendo muitas regras confusas e difíceis de manter.
O problema
O órgão não conseguia receber a doação porque o sistema estava dando timeout.
Investigando o código, encontrei o principal gargalo:
- Dentro de um
forque percorria os itens a serem recebidos, eram feitas várias consultas ao banco por item. - A doação tinha mais de 700 itens.
- Para cada item, eram executadas pelo menos 5 consultas.
Resultado: o processo ultrapassava facilmente 1 minuto de execução.
A solução aplicada
Para resolver isso, fiz o seguinte:
- Movi as consultas para fora do
for. - Percorri a lista apenas para coletar os IDs dos itens.
- Executei uma única consulta ao banco usando essa lista de IDs.
- Montei um
Mapem memória, associando ID → valor. - Dentro do
for, passei a acessar apenas o valor pelo ID, sem novas consultas.
Essa mudança resolveu o principal gargalo e o desempenho melhorou bastante.
Novo desafio: persistência
Após isso, começaram os problemas na hora de salvar os dados:
- O banco de homologação é bem mais lento que o de produção.
- O uso de
mergefazia várias consultas para validar se as entidades já existiam. - Tive problemas com entidades
detached, mas consegui contornar. - Aparentemente, não há muita alternativa ao
merge, já que ele garante a consistência. - Tentei usar
Session.updatediretamente, mas surgiram conflitos com objetos lazy já vinculados a outra sessão.
Conclusão
Consegui resolver o problema no mesmo dia e obter um desempenho bem melhor, eliminando o maior gargalo.
Ainda assim, fiquei com a dúvida:
Existe alguma outra forma mais eficiente e simples de lidar com esse tipo de timeout, especialmente em sistemas legados como esse?
Se alguém já passou por algo parecido ou tiver alguma sugestão, ficarei feliz em ouvir! 😊