example java performance microbenchmark jmh

java - example - ¿Por qué el patrón de encadenamiento StringBuilder sb.append(x).append(y) es más rápido que el estándar sb.append(x); sb.append(y)?



stringbuilder java example (1)

La concatenación de cadenas a + b + c es un patrón muy frecuente en los programas de Java, por lo que HotSpot JVM tiene una optimización especial para él: -XX:+OptimizeStringConcat que está activado por defecto.

HotSpot JVM reconoce el new StringBuilder().append()...append().toString() patrón new StringBuilder().append()...append().toString() en el bytecode y lo traduce al código máquina optimizado sin llamar a los métodos reales de Java y sin asignar objetos intermedios. Es decir, este es un tipo de compuesto JVM intrínseco.

Aquí está el código fuente para esta optimización.

Por otro lado, sb.append(); sb.append(); ... sb.append(); sb.append(); ... sb.append(); sb.append(); ... no se maneja especialmente. Esta secuencia se compila al igual que las llamadas a un método Java normal.

Si vuelve a ejecutar el benchmark con -XX:-OptimizeStringConcat , el rendimiento será el mismo para ambas variantes.

Tengo un microbenchmark que muestra resultados muy extraños:

@BenchmarkMode(Mode.Throughput) @Fork(1) @State(Scope.Thread) @Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS, batchSize = 1000) @Measurement(iterations = 40, time = 1, timeUnit = TimeUnit.SECONDS, batchSize = 1000) public class Chaining { private String a1 = "111111111111111111111111"; private String a2 = "222222222222222222222222"; private String a3 = "333333333333333333333333"; @Benchmark public String typicalChaining() { return new StringBuilder().append(a1).append(a2).append(a3).toString(); } @Benchmark public String noChaining() { StringBuilder sb = new StringBuilder(); sb.append(a1); sb.append(a2); sb.append(a3); return sb.toString(); } }

Estoy esperando que los resultados de ambas pruebas sean los mismos o al menos muy cercanos. Sin embargo, la diferencia es casi 5x:

# Run complete. Total time: 00:01:41 Benchmark Mode Cnt Score Error Units Chaining.noChaining thrpt 40 8538.236 ± 209.924 ops/s Chaining.typicalChaining thrpt 40 36729.523 ± 988.936 ops/s

¿Alguien sabe cómo eso es posible?