Por qué el patrón de encadenamiento StringBuilder es sb.append (x).añadir (y) más rápido que sb normal.append (x); sb.añadir (y)?
Tengo una marca microbench 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();
}
}
Espero 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 es posible?
1 answers
La concatenación de cadenas a + b + c
es un patrón muy frecuente en los programas Java, por lo que HotSpot JVM tiene una optimización especial para ello: -XX:+OptimizeStringConcat
que está activada por defecto.
HotSpot JVM reconoce new StringBuilder().append()...append().toString()
pattern en el bytecode y lo traduce al código máquina optimizado sin llamar a métodos Java reales 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.
En el otro lado, sb.append(); sb.append(); ...
no se maneja especialmente. Esta secuencia se compila igual que un método Java normal llama.
Si vuelve a ejecutar el benchmark con -XX:-OptimizeStringConcat
, el rendimiento será el mismo para ambas variantes.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-03 01:19:59