जवाबों:
JIT संकलक मक्खी पर कोड संकलित करते हैं, उनके निष्पादन से ठीक पहले या जब वे पहले से ही निष्पादित कर रहे होते हैं। इस तरह, वीएम जहां कोड चल रहा है, अनुकूलन को अनुमति देने के लिए कोड निष्पादन में पैटर्न की जांच कर सकता है जो केवल रन-टाइम जानकारी के साथ संभव होगा। इसके अलावा, अगर वीएम तय करता है कि संकलित संस्करण जो भी कारण के लिए पर्याप्त नहीं है (उदाहरण के लिए, बहुत सारे कैश छूट जाते हैं, या कोड अक्सर किसी विशेष अपवाद को फेंकते हैं), यह इसे अलग तरीके से फिर से जोड़ने का निर्णय ले सकता है, जिससे बहुत अधिक होशियार हो जाएगा संकलन।
दूसरी तरफ, C और C ++ कंपाइलर पारंपरिक रूप से JIT नहीं हैं। वे एकल-शॉट में केवल एक बार डेवलपर की मशीन पर संकलन करते हैं और फिर एक निष्पादन योग्य उत्पादन किया जाता है।
जेआईटी सिर्फ-इन-टाइम कंपाइलर के लिए छोटा है, और नाम मिसाइल है: रनटाइम के दौरान, यह सार्थक कोड अनुकूलन का निर्धारण करता है और उन्हें लागू करता है। यह सामान्य संकलक को प्रतिस्थापित नहीं करता है लेकिन दुभाषियों का हिस्सा है। ध्यान दें कि मध्यवर्ती कोड का उपयोग करने वाली जावा जैसी भाषाओं में दोनों हैं : स्रोत से मध्यवर्ती कोड अनुवाद के लिए एक सामान्य संकलक, और प्रदर्शन में वृद्धि के लिए दुभाषिया में शामिल एक जेआईटी।
कोड अनुकूलन निश्चित रूप से "शास्त्रीय" संकलक द्वारा किया जा सकता है, लेकिन मुख्य अंतर पर ध्यान दें: जेआईटी संकलक के पास रनटाइम पर डेटा तक पहुंच है। यह बहुत बड़ा लाभ है; इसका सही तरीके से दोहन करना मुश्किल हो सकता है, जाहिर है।
उदाहरण के लिए, इस तरह से कोड पर विचार करें:
m(a : String, b : String, k : Int) {
val c : Int;
switch (k) {
case 0 : { c = 7; break; }
...
case 17 : { c = complicatedMethod(k, a+b); break; }
}
return a.length + b.length - c + 2*k;
}
एक सामान्य संकलक इस बारे में बहुत कुछ नहीं कर सकता है। एक जेआईटी संकलक, हालांकि, यह पता लगा सकता है कि m
केवल k==0
किसी कारण से कहा जाता है (सामान जो समय के साथ कोड परिवर्तन के रूप में हो सकता है); यह तब कोड का एक छोटा संस्करण बना सकता है (और इसे मूल कोड में संकलित कर सकता है, हालांकि मैं इसे एक मामूली बिंदु मानता हूं, वैचारिक रूप से):
m(a : String, b : String) {
return a.length + b.length - 7;
}
इस बिंदु पर, यह शायद विधि कॉल को भी इनलाइन कर देगा क्योंकि यह अब तुच्छ है।
जाहिरा तौर पर, सूर्य ने javac
जावा 6 में उपयोग किए जाने वाले अधिकांश अनुकूलन को खारिज कर दिया ; मुझे बताया गया है कि उन आशावादों ने जेआईटी के लिए बहुत कुछ करना मुश्किल बना दिया, और अंत में भोले संकलित कोड तेजी से भागे। जाओ पता लगाओ।
m
एक ऐसे संस्करण से प्रतिस्थापित नहीं कर सकेगी, जिसने जांच नहीं की थी k
क्योंकि यह साबित करने में असमर्थ होगा कि m
इसे कभी भी गैर-शून्य के साथ नहीं बुलाया जाएगा k
, लेकिन यहां तक कि यह साबित करने में सक्षम होने के बिना कि यह बदल नहीं सकता है यह static miss_count; if (k==0) return a.length+b.length-7; else if (miss_count++ < 16) { ... unoptimized code for
एम के साथ ...} else { ... consider other optimizations...}
।
k=0
हमेशा , मतलब यह इनपुट या पर्यावरण का कार्य नहीं है, क्या परीक्षण को गिराना सुरक्षित है - लेकिन यह निर्धारित करने के लिए स्थैतिक विश्लेषण की आवश्यकता होती है, जो बहुत महंगा है और इस प्रकार केवल संकलन समय पर सस्ती है। एक JIT तब जीत सकती है जब कोड के एक ब्लॉक के माध्यम से एक रास्ता दूसरों की तुलना में अधिक बार लिया जाता है, और इस पथ के लिए विशेष कोड का एक संस्करण बहुत तेज होगा। लेकिन जेआईटी अभी भी यह जांचने के लिए परीक्षण करेगी कि क्या तेज़ रास्ता लागू होता है , और यदि नहीं तो "धीमा रास्ता" अपनाएं।
Base* p
पैरामीटर लेता है , और इसके माध्यम से वर्चुअल फ़ंक्शन कॉल करता है; रनटाइम विश्लेषण से पता चलता है कि हमेशा (या लगभग हमेशा) इंगित की गई वास्तविक वस्तु Derived1
प्रकार की लगती है । JIT Derived1
विधियों को स्टेटिकली सॉल्व्ड (या इनबिल्ड) कॉल के साथ फंक्शन का एक नया वर्जन तैयार कर सकता है। यह कोड एक सशर्त से पहले होगा जो यह जाँचता है कि क्या p
अपेक्षित Derived1
तालिका के लिए संभावित सूचक इंगित करता है ; यदि नहीं, तो यह इसके धीमे गतिशील तरीके से हल किए गए कॉल के साथ फ़ंक्शन के मूल संस्करण में कूदता है।