2010-02-21 11 views
20

कोड का दूसरा टुकड़ा तेजी से क्यों है?जावा में मैन्युअल मुक्केबाजी बनाम Autoboxing

Map<Integer, Double> map = new HashMap<Integer, Double>(); 
for (int i = 0; i < 50000; i++) { 
    for (double j = 0.0; j < 10000; j++) { 
     map.put(i, j); 
    } 
} 

Map<Integer, Double> map=new HashMap<Integer, Double>(); 
for (int i = 0; i < 50000; i++) { 
    for (double j = 0.0; j < 10000; j++) {    
     map.put(new Integer(i), new Double(j)); 
    } 
} 
+0

दोनों हिस्सों को चारों ओर लपेटने की कोशिश करें और इसे फिर से माइक्रोबेंमार्क करें। – BalusC

+2

क्योंकि आपके प्रदूषित सूक्ष्म-बेंचमार्क के बाहर जो गलत है, इससे कोई फर्क नहीं पड़ता क्योंकि यह अंततः अनुकूलित हो जाएगा लेकिन अंततः वास्तविक दुनिया में जेआईटी। –

उत्तर

46

autoboxing Integer.valueOf, जो आंतरिक रूप से 127 के लिए छोटे पूर्णांक (डिफ़ॉल्ट -128 द्वारा लिए पूर्णांक वस्तुओं कैश का उपयोग करता है, लेकिन अधिकतम मूल्य "java.lang.Integer.IntegerCache.high" संपत्ति के साथ विन्यस्त किया जा सकता - स्रोत कोड देख Integer.valueOf का), इसलिए यह सीधे new Integer पर कॉल करने से अलग है। क्योंकि Integer.valueOfnew Integer पर कॉल करने से पहले पूर्णांक मान की परिमाण के लिए त्वरित जांच करता है, यह new Integer पर कॉल करने के लिए थोड़ा तेज़ है (हालांकि यदि आपके पास बहुत छोटे पूर्णांक हैं तो यह अधिक स्मृति का उपयोग करता है)। जावा में आवंटन बहुत तेज़ है, और जीसी करने का समय लाइव अल्पकालिक वस्तुओं की संख्या के समान है (यानी कचरे की मात्रा के अनुपात में नहीं), इसलिए जीसी भी बहुत तेज़ है।

लेकिन जेवीएम संस्करण और कौन सा अनुकूलन सक्षम है, के आधार पर स्केलर प्रतिस्थापन अनुकूलन है, जो अल्पकालिक वस्तुओं को आवंटित करते समय बहुत बड़ा प्रदर्शन अंतर उत्पन्न कर सकता है (आपके उदाहरण में ऑप्टिमाइज़ेशन नहीं किया जा सकता है, क्योंकि आप किसी मानचित्र में वस्तुओं को संग्रहीत कर रहे हैं, लेकिन कई अन्य परिस्थितियों में यह उपयोगी है)।

हाल ही में जेवीएम संस्करणों में scalar replacement अनुकूलन है (1.6.0_18 को छोड़कर जहां से बचने का विश्लेषण temporarily disabled है), जिसका अर्थ है कि अल्पकालिक वस्तुओं के आवंटन को अनुकूलित किया जा सकता है। जब JVM में स्केलर प्रतिस्थापन नया था, तो किसी ने a benchmark बनाया जहां आपके समान कोड था। परिणाम यह था कि प्राइमेटिव्स का उपयोग करने वाला कोड सबसे तेज़ था, स्पष्ट new Integer() कॉल वाले कोड लगभग प्राइमेटिव का उपयोग करने वाले जितना तेज़ थे, और कोड जो ऑटोबॉक्सिंग का उपयोग करता था वह बहुत धीमा था। ऐसा इसलिए था क्योंकि ऑटोबॉक्सिंग Integer.valueOf का उपयोग करता है और कम से कम वापस स्केलर प्रतिस्थापन अनुकूलन उस विशेष मामले को ध्यान में नहीं लेता था। मुझे नहीं पता कि तब से अनुकूलन में सुधार हुआ है या नहीं।

+1

"क्योंकि Integer.valueOf नए इंटीजर को कॉल करने से पहले पूर्णांक के आकार के लिए त्वरित जांच करता है"। एक जावा इंटीजर हमेशा एक ही आकार होता है। –

+4

उसका मतलब है कि यह जांचने के लिए int मान को जांचता है कि यह कैश किए गए मानों की सीमा के भीतर है या नहीं। – ColinD

+1

मूल्य और आकार के अलग-अलग अर्थ हैं। –

7

क्योंकि माइक्रोबेंचमार्क के परिणाम अविश्वसनीय हैं?

इसके अलावा, ऑटो-मुक्केबाजी Integer.valueOf() और Double.valueOf() का उपयोग करके किया जाता है, कन्स्ट्रक्टर नहीं।

14

ऑटोबॉक्सिंग Integer.valueOf और Double.valueOf का उपयोग करेगा। उन तरीकों को बुलाए जाने में कुछ ओवरहेड है (हालांकि यह अंततः रेखांकित हो जाएगा)। Integer.valueOf पूल किए गए उदाहरणों का उपयोग करने के लिए कुछ मूल्यों की जांच करता है, जो आपके कोड में अक्सर जीत नहीं होती है (हालांकि यह ढेर आकार को कम कर सकती है)। पूल किए गए उदाहरण एक जीत हो सकते हैं जहां वे ढेर आकार, जीसी टाइम्स को कम करते हैं और समानता परीक्षण प्रदर्शन में भी सुधार कर सकते हैं ..

लेकिन, सामान्य रूप से, यह एक सूक्ष्मदर्शीकरण है जिसे आपको सामान्य रूप से अनदेखा करना चाहिए।

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