Há muito tempo eu tenho em mente a afirmação: “StringBuilder tem uma performance melhor que String”.
Resolvi usar a afirmação acima como motivação para me ambientar com o JMH(Java Microbenchmark Harness) e comprovar na prática.
Talvez você já tenha visto benchmarks simples usando System.currentTimeMillis() ou System.nanoTime(), essas abordagens funcionam, mas o JMH oferece medições muito mais precisas, pois considera fatores da JVM que podem distorcer os resultados.
O JMH está disponível aqui: https://lnkd.in/dzE95pjB
Para o benchmark, criei um loop com 100.000 iterações fazendo concatenação de strings, com a mesma lógica tanto para String quanto para StringBuilder.
🔎 Resultado:
String: 471,807 ms
StringBuilder: 0,125 ms
A diferença é enorme, e o motivo é simples:
String é imutável: cada concatenação cria um novo objeto, gerando muitos objetos temporários. Isso aumenta a atuação do Garbage Collector, afetando a performance.
StringBuilder é mutável: todas as concatenações acontecem no mesmo objeto, evitando overhead desnecessário.
Esse benchmark me deixou ainda mais atento sobre fazer escolhas conscientes quando a performance é crítica.
Vale lembrar que existe também o StringBuffer, que é thread-safe e, por isso, naturalmente um pouco(sutil) mais lento que o StringBuilder. Mas em alguns benchmarks, o StringBuffer pode até ter performance tão boa quanto StringBuilder, mas deixo esse comparativo para um próximo post 😉
Usar System.currentTimeMillis() ou System.nanoTime() funciona para medições simples, mas quando se busca alta precisão, o JMH se destaca. Ele leva em conta fatores da JVM, como JIT, Garbage Collector e otimizações de compilação, oferecendo resultados confiáveis e reproduzíveis. Conhecer o JMH é importante, porque cedo ou tarde podemos precisar avaliar a performance de forma precisa e segura em nossos códigos Java.