45 votes

Pourquoi le modèle de chaînage StringBuilder sb.append (x) .append (y) est-il plus rapide que sb.append (x) classique? sb.append (y)?

J'ai un micro-repère qui montre des résultats très étranges:

 @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();
    }
}
 

Je m'attends à ce que les résultats des deux tests soient identiques ou du moins très proches. Cependant, la différence est presque 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
 

Est-ce que quelqu'un sait comment c'est possible?

56voto

apangin Points 4693

La concaténation de chaîne a + b + c est très fréquent motif dans des programmes Java, donc de la JVM HotSpot a une optimisation particulière pour elle: -XX:+OptimizeStringConcat qui est activé par défaut.

JVM HotSpot reconnaît new StringBuilder().append()...append().toString() modèle dans le bytecode et traduit de l'optimisation de code machine sans appel de réelles méthodes de Java et sans allocation des objets intermédiaires. I. e. c'est une sorte de composé de la JVM intrinsèque.

Voici le code source pour cette optimisation.

De l'autre côté, sb.append(); sb.append(); ... n'est pas traitée spécialement. Cette séquence est compilé comme un Java appels de méthode.

Si vous exécutez à nouveau l'indice de référence -XX:-OptimizeStringConcat, le rendement sera le même pour les deux variantes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X