2017-02-12 19 views
16

Bir kriter vardır:Dize birleştirme, bir Tamsayıyı bir String'e dönüştürmek için String.valueOf'tan neden daha hızlıdır?

Benchmark           Mode Cnt  Score  Error Units 
StringConcatTest.emptyStringInt     thrpt 40 66045.741 ± 1306.280 ops/s 
StringConcatTest.valueOfInt      thrpt 40 43947.708 ± 1140.078 ops/s 

O tamsayı sayı ile boş dize bitiştirme String.value (100) çağırarak% 30 daha hızlı olduğunu göstermektedir: Burada

@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 StringConcatTest { 

    private int aInt; 

    @Setup 
    public void prepare() { 
     aInt = 100; 
    } 

    @Benchmark 
    public String emptyStringInt() { 
     return "" + aInt; 
    } 

    @Benchmark 
    public String valueOfInt() { 
     return String.valueOf(aInt); 
    } 

} 

Ve sonucudur. Ben "" + 100

new StringBuilder().append(100).toString() 

dönüştürülür ve hızlı yapar -XX:+OptimizeStringConcat optimizasyonu uygulanır anlıyoruz. Anlamadığım şey, neden valueOf'un kendisinin birleşimden daha yavaş olmasıdır. Birisi tam olarak neler olduğunu açıklayabilir ve neden "+ 100 daha hızlıdır. OptimizeStringConcat hangi sihri yapar? String.valueOf() genel derleyici optimizasyonları dayanıyor yaparken belirttiğimiz gibi

+1

'' '+ 100', derleyicinin sabit olarak tanıması için muhtemelen daha nettir ... –

+0

Kaynak değeri' valueOf' için bakabilirsiniz. Nesne türlerini algılamaya gayret ettiğime eminim, bu da int ilkeliğinizin otomatik kutulanması ve –

+1

bunlardan biri yöntem çağrısıdır. Diğeri ise, derleyici istediği gibi derleyebilir. –

cevap

12

, HotSpot JVM StringBuilder desen tanır ve son derece ayarlı elle yazılmış IR grafiğinin değiştirir -XX:+OptimizeStringConcat optimizasyonu var.

Ben ettik bulundu oluşturulan derleme kod analiz ederek aşağıdaki önemli farklılıklar: Integer.toString yarattığı dizi tahsisi gibi sonra temizlenir iken

  • Optimize concat, sonuç dizesi için oluşturulan sıfır char[] dizi değil diğer normal nesneler. Integer.getChars kontrol İlgili dizi sınırları ile table lookup kullanırken
  • Optimize concat, basit addition of '0' constant tarafından chars basamak çevirir vb

Orada PhaseStringOpts::int_getChars vs. Integer.getChars uygulanmasında diğer küçük farklılıklar vardır, ama bunlar sanırım performans için bu önemli değil. Daha büyük bir miktarda (örneğin 1234567890) alırsak


btw, performans farkı nedeniyle, aynı anda iki basamak dönüştürür Integer.getChars bir extra loop önemsiz olacaktır.

İlgili konular