2012-11-01 18 views
5

यह भी सोचा कि यह इसका मुख्य उद्देश्य नहीं है, मैंने हमेशा सोचा है कि final कीवर्ड (कुछ स्थितियों और वीएम कार्यान्वयन में) जेआईटी की मदद कर सकता है।
यह शहरी किंवदंती हो सकता है लेकिन मैंने कभी कल्पना नहीं की है कि final फ़ील्ड सेट करना प्रदर्शन को नकारात्मक रूप से प्रभावित कर सकता है।

तक मुझे लगता है कि जैसे कुछ कोड में भाग: private static int [] myArray = new int [THRESHOLD];
W7 64 बिट के तहत और 10 लगातार रन के आधार पर, मैं मिलता है:स्थैतिक अंतिम क्षेत्र, स्थैतिक क्षेत्र और प्रदर्शन

private static final int THRESHOLD = 10_000_000; 
    private static int [] myArray = new int [THRESHOLD]; 

    public static void main(String... args) { 
     final long begin = System.currentTimeMillis(); 

     //Playing with myArray 
     int index1,index2; 
     for(index1 = THRESHOLD - 1; index1 > 1; index1--) 
      myArray[index1] = 42;    //Array initial data 
     for(index1 = THRESHOLD - 1; index1 > 1; index1--) { 
              //Filling the array 
      for(index2 = index1 << 1; index2 < THRESHOLD; index2 += index1) 
       myArray[index2] += 32; 
     } 

     long result = 0; 
     for(index1 = THRESHOLD - 1; index1 > 1; index1-=100) 
      result += myArray[index1]; 

     //Stop playing, let's see how long it took 
     System.out.println(result); 
     System.out.println((System.currentTimeMillis())-begin+"ms"); 
    } 


के पर एक नजर है निम्न परिणाम:

  1. THRESHOLD = 10^7, 1.7.0u09 ग्राहक वी एम (Oracle):

    • ~ 2133ms में चलता है जब myArray अंतिम नहीं है।
    • ~ 2287ms में चलता है जब myArray अंतिम है।
    • -सर्वर वीएम इसी तरह के आंकड़े पैदा करता है iee 2131ms और 2284ms।

  2. THRESHOLD = 3x10^7, 1.7.0u09 ग्राहक वी एम (Oracle):
    ~ 7647ms में

    • रन जब myArray अंतिम नहीं है।
    • ~ 8190ms में चलता है जब myArray अंतिम है।
    • -सर्वर वीएम ~ 7653ms और ~ 8150ms का उत्पादन करता है।

  3. THRESHOLD = 3x10^7, 1.7.0u01 ग्राहक वी एम (Oracle):
    ~ 8166ms में

    • रन जब myArray अंतिम नहीं है।
    • ~ 9 6 9 4 एमएस में चलता है जब myArray अंतिम है। यह 15% से अधिक अंतर है!
    • -सर्वर वीएम गैर-अंतिम संस्करण के पक्ष में एक उपेक्षित अंतर उत्पन्न करता है, लगभग 1%।

टिप्पणी: मैं बाईटकोड मेरे सभी परीक्षणों के लिए JDK 1.7.0u09 के javac द्वारा उत्पादित किया करते थे। उत्पादित बाइटकोड myArray घोषणा के अलावा दोनों संस्करणों के लिए बिल्कुल समान है, जिसकी अपेक्षा की गई थी।

तो static final myArray वाला संस्करण static myArray के साथ धीमा क्यों है?


संपादित करें (मेरी स्निपेट की Aubin के संस्करण का उपयोग कर):

ऐसा लगता है कि केवल बिना final कीवर्ड के साथ संस्करण और एक के बीच मतभेद पहली यात्रा में निहित है। किसी भी तरह, final वाला संस्करण पहले पुनरावृत्ति के बिना अपने समकक्ष से हमेशा धीमा होता है, फिर अगले पुनरावृत्तियों के समान समय होते हैं।

उदाहरण के लिए, THRESHOLD = 10^8 के साथ और 1.7.0u0 9 क्लाइंट के साथ चल रहा है पहली गणना में लगभग 35s लगते हैं जबकि दूसरा 'केवल' 30 लेता है।

स्पष्ट रूप से वीएम ने एक अनुकूलन किया, यह था कि कार्रवाई में जेआईटी और यह पहले क्यों नहीं लाया गया था (उदाहरण के लिए नेस्टेड लूप के दूसरे स्तर को संकलित करके, यह हिस्सा हॉटस्पॉट था)?

ध्यान दें कि मेरी टिप्पणी अभी भी 1.7.0u01 क्लाइंट वीएम के साथ मान्य है। उस संस्करण के साथ (और शायद पहले रिलीज़), वाला कोड इस कीवर्ड के बिना एक से धीमा चलता है: 200 पुनरावृत्तियों के आधार पर 2671ms बनाम 2331ms।

+2

बस 2 सेकंड रनटाइम? ऐसा मत सोचो कि जेआईटी ने वास्तव में कुछ गंभीर अनुकूलन किया है। –

+4

10 रन पर्याप्त नहीं हैं, 1000 बेहतर होंगे, और पहले रन को – Aubin

+0

@Aubin में नहीं लिया जा सकता है, इसमें कुछ समय लगेगा, जब मैं खत्म हो जाऊंगा तो पोस्ट को अपडेट कर दूंगा। – Jerome

उत्तर

4

आईएमएचओ, System.out.println (परिणाम) का समय जोड़ा नहीं जाना चाहिए क्योंकि I/O अत्यधिक चर और समय लेने वाला है।

मुझे लगता है कि println() प्रभाव का कारक बड़ा है, वास्तव में अंतिम प्रभाव से बड़ा है।

मैं इस प्रकार प्रदर्शन परीक्षण लिखने के लिए प्रस्ताव:

public class Perf { 
    private static final int THRESHOLD = 10_000_000; 
    private static final int[] myArray = new int[THRESHOLD]; 
    private static /* */ long min = Integer.MAX_VALUE; 
    private static /* */ long max = 0L; 
    private static /* */ long sum = 0L; 

    private static void perf(int iteration) { 
     final long begin = System.currentTimeMillis(); 

     int index1, index2; 
     for(index1 = THRESHOLD - 1; index1 > 1; index1--) { 
     myArray[ index1 ] = 42; 
     } 
     for(index1 = THRESHOLD - 1; index1 > 1; index1--) { 
     for(index2 = index1 << 1; index2 < THRESHOLD; index2 += index1) { 
      myArray[ index2 ] += 32; 
     } 
     } 
     long result = 0; 
     for(index1 = THRESHOLD - 1; index1 > 1; index1 -= 100) { 
     result += myArray[ index1 ]; 
     } 
     if(iteration > 0) { 
     long delta = System.currentTimeMillis() - begin; 
     sum += delta; 
     min = Math.min( min, delta); 
     max = Math.max( max, delta); 
     System.out.println(iteration + ": " + result); 
     } 
    } 

    public static void main(String[] args) { 
     for(int iteration = 0; iteration < 1000; ++iteration) { 
     perf(iteration); 
     } 
     long average = sum/999;// the first is ignored 
     System.out.println("Min : " + min  + " ms"); 
     System.out.println("Average: " + average + " ms"); 
     System.out.println("Max : " + max  + " ms"); 
    } 
} 

और केवल 10 पुनरावृत्तियों के परिणाम हैं:

अंतिम साथ

:

Min : 7645 ms 
Average: 7659 ms 
Max : 7926 ms 

अंतिम बिना:

Min : 7629 ms 
Average: 7780 ms 
Max : 7957 ms 

मेरा सुझाव है कि पाठक इस परीक्षा को चलाएं और तुलना करने के लिए अपने परिणाम पोस्ट करें।

+0

यह वास्तव में अंतिम रूप का प्रभाव है जिसमें मुझे रूचि है। Println (परिणाम) के बारे में, मैंने यह सुनिश्चित करने के लिए इसका उपयोग किया कि परिणाम पूरी तरह से गणना की गई है (कौन जानता है ...)। – Jerome

+0

हां, ऐसा इसलिए है क्योंकि आपको इसे मापना नहीं है – Aubin

+0

@ औबिन: विषय से बाहर: "AMUO" का क्या अर्थ है? –

संबंधित मुद्दे