2012-10-26 17 views
16

Java listesi yineleme kodunda bazı mikro ölçütler çalıştırıyorum. Zamanlama çalıştırıldığında arka planda hiçbir şey olmadığından emin olmak için -XX: + PrintCompilation ve -verbose: gc bayrakları kullandım. Ancak, çıktıda anlayamadığım bir şey görüyorum.-XX: + PrintCompilation çıkışının anlaşılması

Burada üzerinde kriter çalıştırıyorum, kod:

import java.util.ArrayList; 
import java.util.List; 

public class PerformantIteration { 

    private static int theSum = 0; 

    public static void main(String[] args) { 
     System.out.println("Starting microbenchmark on iterating over collections with a call to size() in each iteration"); 
     List<Integer> nums = new ArrayList<Integer>(); 
     for(int i=0; i<50000; i++) { 
      nums.add(i); 
     } 

     System.out.println("Warming up ..."); 
     //warmup... make sure all JIT comliling is done before the actual benchmarking starts 
     for(int i=0; i<10; i++) { 
      iterateWithConstantSize(nums); 
      iterateWithDynamicSize(nums); 
     } 

     //actual   
     System.out.println("Starting the actual test"); 
     long constantSizeBenchmark = iterateWithConstantSize(nums); 
     long dynamicSizeBenchmark = iterateWithDynamicSize(nums); 
     System.out.println("Test completed... printing results"); 

     System.out.println("constantSizeBenchmark : " + constantSizeBenchmark); 
     System.out.println("dynamicSizeBenchmark : " + dynamicSizeBenchmark); 
     System.out.println("dynamicSizeBenchmark/constantSizeBenchmark : " + ((double)dynamicSizeBenchmark/(double)constantSizeBenchmark)); 
    } 

    private static long iterateWithDynamicSize(List<Integer> nums) { 
     int sum=0; 
     long start = System.nanoTime();   
     for(int i=0; i<nums.size(); i++) { 
      // appear to do something useful 
      sum += nums.get(i); 
     }  
     long end = System.nanoTime(); 
     setSum(sum); 
     return end-start; 
    } 

    private static long iterateWithConstantSize(List<Integer> nums) { 
     int count = nums.size(); 
     int sum=0; 
     long start = System.nanoTime();   
     for(int i=0; i<count; i++) { 
      // appear to do something useful 
      sum += nums.get(i); 
     } 
     long end = System.nanoTime(); 
     setSum(sum); 
     return end-start; 
    } 

    // invocations to this method simply exist to fool the VM into thinking that we are doing something useful in the loop 
    private static void setSum(int sum) { 
     theSum = sum;  
    } 

} 


Çıktı İşte.

152 1  java.lang.String::charAt (33 bytes) 
    160 2  java.lang.String::indexOf (151 bytes) 
    165 3Starting microbenchmark on iterating over collections with a call to size() in each iteration  java.lang.String::hashCode (60 bytes) 
    171 4  sun.nio.cs.UTF_8$Encoder::encodeArrayLoop (490 bytes) 
    183 5 
     java.lang.String::lastIndexOf (156 bytes) 
    197 6  java.io.UnixFileSystem::normalize (75 bytes) 
    200 7  java.lang.Object::<init> (1 bytes) 
    205 8  java.lang.Number::<init> (5 bytes) 
    206 9  java.lang.Integer::<init> (10 bytes) 
    211 10  java.util.ArrayList::add (29 bytes) 
    211 11  java.util.ArrayList::ensureCapacity (58 bytes) 
    217 12  java.lang.Integer::valueOf (35 bytes) 
    221 1%  performance.api.PerformantIteration::main @ 21 (173 bytes) 
Warming up ... 
    252 13  java.util.ArrayList::get (11 bytes) 
    252 14  java.util.ArrayList::rangeCheck (22 bytes) 
    253 15  java.util.ArrayList::elementData (7 bytes) 
    260 2%  performance.api.PerformantIteration::iterateWithConstantSize @ 19 (59 bytes) 
    268 3%  performance.api.PerformantIteration::iterateWithDynamicSize @ 12 (57 bytes) 
    272 16  performance.api.PerformantIteration::iterateWithConstantSize (59 bytes) 
    278 17  performance.api.PerformantIteration::iterateWithDynamicSize (57 bytes) 
Starting the actual test 
Test completed... printing results 
constantSizeBenchmark : 301688 
dynamicSizeBenchmark : 782602 
dynamicSizeBenchmark/constantSizeBenchmark : 2.5940773249184588 


ben çıkışından bu dört satırları anlamıyorum.

260 2%  performance.api.PerformantIteration::iterateWithConstantSize @ 19 (59 bytes) 
268 3%  performance.api.PerformantIteration::iterateWithDynamicSize @ 12 (57 bytes) 
272 16  performance.api.PerformantIteration::iterateWithConstantSize (59 bytes) 
278 17  performance.api.PerformantIteration::iterateWithDynamicSize (57 bytes) 


  • Neden hem bu yöntemler iki kez derlenmektedir?
  • Bu çıktıyı nasıl okurum? Farklı sayılar ne anlama geliyor?
+0

Teşekkür @Thomas Jungblut emin değil başlık – Parag

+2

np, burada derleme hakkında iyi bir kaynaktır: https://gist.github.com/1165804#file_notes.md –

cevap

15

Thomas Jungblut tarafından gönderilen bu link yardımı ile kendi sorumu yanıtlamaya çalışacağım.

260 2%  performance.api.PerformantIteration::iterateWithConstantSize @ 19 (59 bytes) 
268 3%  performance.api.PerformantIteration::iterateWithDynamicSize @ 12 (57 bytes) 
272 16  performance.api.PerformantIteration::iterateWithConstantSize (59 bytes) 
278 17  performance.api.PerformantIteration::iterateWithDynamicSize (57 bytes) 

Birinci sütun

İlk sütun '260' zaman damgasıdır.

ikinci sütun İkinci sütun compilation_id ve method_attributes olup. Bir HotSpot derlemesi tetiklendiğinde, her derleme birimi bir derleme kimliği alır. İkinci sütundaki sayı derleme kimliğidir. JIT derlemesi ve OSR derlemesi, derleme kimliği için iki farklı diziye sahiptir. Yani% 1 ve 1 farklı derleme birimleridir. İlk iki satırdaki% 'si, bunun bir OSR derlemesi olduğu gerçeğine işaret eder. Bir OSR derlemesi tetiklendi çünkü kod büyük bir döngü üzerinde dönüyordu ve VM bu kodun sıcak olduğunu belirledi. Böylece bir OSR derlemesi tetiklendi; bu, VM'nin Yığın Yedeği Değişimi yapmasını ve hazır olduğunda, optimize edilmiş kodun üzerine geçmesini sağlayacaktı.

Üçüncü sütun

üçüncü bir kolon performance.api.PerformantIteration::iterateWithConstantSize yöntem adıdır. OSR derleme olur ve zaman yok değilken

Dördüncü sütun

dördüncü sütun yine farklıdır. Önce ortak parçalara bakalım. Dördüncü sütunun sonu (59 bayt), derleme biriminin bayt kodunda (derlenmiş kodun boyutuna değil) boyutunu ifade eder. OSR derlemesinde @ 19 bölüm osr_bci'ye atıfta bulunur."Osr_bci" denir OSR derleme tetikleyen onun baytkodu indeksi (BCI) ve yerine göre tanımlanan bir Java yönteminde

A "Yer" - Yukarıda belirtilen bağlantıdan alıntı yapacağım . Bir OSR-derlenmiş nimlhod sadece osr_bci'den girilebilir; Orada osr_bci farklı olduğu sürece, aynı zamanında aynı yöntemin çoklu OSR-derlenmiş sürümleri olabilir.

Son olarak, yöntem neden iki kez derlenmişti?

ilk halka (örnekte) ısınma kodu nedeniyle çalışırken muhtemelen ne bir OSR derlenmesi ve ikinci derleme daha derlenmiş kod optimize etmek için muhtemelen, bir tam zamanında derleme?

+0

Isınma sırasında OSR kodu alıyorsanız "yanlış yapıyorsunuz". Ayrıca JVM'nin argümanlarını listeleyebilir, sadece C1 (istemci/dilsiz derleyici) ve C2 (daha akıllı, yavaş derleyici) olabilir. Yeniden derleme aynı zamanda deoptimizasyonun bir sonucudur. Oluşturulan kodu listelemenin en kolay (?) Yolu, C1 dizilerini görürseniz, C1 kodu olduğunu bilirsiniz. – bestsss

+0

@bestsss Neden bu? OSR derlemesinin gerçekleştiğini düşünüyorum çünkü örnek ısınma kodu büyük bir döngü çağırıyor. – Parag

+0

Benim amacım, bir şeyleri ısıtmaya çalışırsanız, OSR'den kaçınmanız, daha küçük yöntemlerle bölmeniz gerekir. – bestsss

-1

Ben o zaman çağırma Sayaç tigger yöntemini değiştirmek, ilk defa OSR oldu düşünüyorum compilar den + PrintCompilation: Ben XX kaçırmış nasıl (PS üzgünüm, ingilizce olan havuz)