2017-05-24 32 views
5

को ध्यान में रखते कोड:क्या हॉटस्पॉट इनलाइन लैम्ब्डा फ़ंक्शन कॉल कर सकता है?

someList.forEach(x -> System.out.format("element %s", x)); 

सैद्धांतिक रूप से, यह इस कोड को इनलाइन और पहली forEach विधि इनलाइन करने, और फिर inlined forEach कोड में लैम्ब्डा समारोह शरीर को इनलाइन द्वारा अप्रत्यक्ष फ़ंक्शन कॉल समाप्त करने के लिए संभव हो जाना चाहिए।

क्या हॉटस्पॉट इस अनुकूलन को करने में सक्षम है? क्या प्रतिबंध किसी विशेष परिस्थिति में किया जाता है या नहीं, यह नियंत्रित करता है?

उत्तर

4

आपकी लैम्ब्डा अभिव्यक्ति को सामान्य विधि में संकलित किया गया है, जबकि जेआरई कार्यात्मक इंटरफ़ेस को पूरा करने और उस विधि को कॉल करने वाली कक्षा उत्पन्न करेगा। वर्तमान हॉटस्पॉट संस्करणों में, यह जेनरेट क्लास लगभग सामान्य वर्ग की तरह काम करता है, मुख्य अंतर यह है कि यह private लक्ष्य विधियों का आह्वान कर सकता है और यह ClassLoader द्वारा वापस संदर्भित नहीं किया गया है।

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

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

+0

यह भी देखें [जावा लैम्ब्डा फ़ंक्शंस कैसे संकलित किए जाएंगे?] (Https://stackoverflow.com/q/16827262/2711488) – Holger

+2

आपको सही ढंग से याद है: 'intx MaxInlineLevel = 9'। – Eugene

3

यह वास्तव में साबित करना वास्तव में आसान है।

for (int i = 0; i < 100_000; ++i) { 
     Stream.of(1, 2, 3, 4) 
       .map(x -> x * 2) 
       .collect(Collectors.toList()); 
} 

जब मैं इस संकलन मैं देख सकता हूँ कि लैम्ब्डा अभिव्यक्ति के लिए उत्पन्न de-sugared विधि (javap के माध्यम से) कहा जाता है: यहाँ कुछ बहुत ही सरल कोड है lambda$main$0 (JDK-9 में है, लेकिन यह नहीं है बहुत मायने रखता है)।

और फिर मैं बस के साथ इस कोड चला सकते हैं:

Inline::lambda$main$0 (10 bytes) inline (hot) 

तो इस तरह के एक विधि के लिए इनलाइन किए जाने वाले हमेशा की तरह काम करता है:

java -XX:-TieredCompilation 
     -XX:CICompilerCount=1 
     -XX:+UnlockDiagnosticVMOptions 
     -XX:+PrintCompilation 
     -XX:+PrintInlining 
     -XX:CompileCommand="print, *.lambda" 
     InlineLambdaTest 
     > inline.txt 

और फ़ाइल को देख वहाँ इस तरह लाइनें हैं। ध्यान दें कि ...lambda... के साथ शुरू होने वाली कई और रेखाएं होंगी क्योंकि आंतरिक रूप से कई अन्य स्थान हैं जो लैम्ब्डा अभिव्यक्ति का उपयोग करते हैं जिन्हें गर्म भी माना जाता है।

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