कैसे एक सामान्य संकलक से एक JIT संकलक अलग है?


22

जावा, रूबी, और पायथन जैसी भाषाओं के लिए जेआईटी संकलक के बारे में बहुत प्रचार किया गया है। JIT कंपाइलर C / C ++ कंपाइलर से अलग कैसे हैं, और जावा, रूबी या पायथन के लिए लिखे गए कंपाइलर्स को JIT कंपाइलर क्यों कहा जाता है, जबकि C / C ++ कंपाइलर को सिर्फ कंपाइलर कहा जाता है?

जवाबों:


17

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

दूसरी तरफ, C और C ++ कंपाइलर पारंपरिक रूप से JIT नहीं हैं। वे एकल-शॉट में केवल एक बार डेवलपर की मशीन पर संकलन करते हैं और फिर एक निष्पादन योग्य उत्पादन किया जाता है।


क्या जेआईटी कंपाइलर्स हैं जो कैश मिस का ट्रैक रखते हैं, और तदनुसार उनकी संकलन रणनीति को अनुकूलित करते हैं? @ विक्टर
मार्टिन बर्जर

@MartinBerger मुझे नहीं पता कि क्या कोई उपलब्ध JIT कंपाइलर ऐसा करते हैं लेकिन क्यों नहीं? जैसे-जैसे कंप्यूटर अधिक शक्तिशाली होते हैं और कंप्यूटर विज्ञान विकसित होता है, लोग प्रोग्राम में अधिक अनुकूलन लागू कर सकते हैं। उदाहरण के लिए जब जावा का जन्म हुआ था, तो यह बहुत धीमा है, शायद संकलित लोगों की तुलना में 20 गुना है, लेकिन अब प्रदर्शन बहुत अधिक नहीं है और कुछ संकलक की तुलना में हो सकता है
फुल्विक

मैंने कुछ समय पहले कुछ ब्लॉग पोस्ट पर यह सुना है। कंपाइलर वर्तमान सीपीयू पर अलग-अलग निर्भर हो सकता है। उदाहरण के लिए यदि यह पता लगाता है कि सीपीयू SSE / AVX को सपोर्ट करता है तो यह अपने आप कुछ कोड को वेक्टर कर सकता है। जब नए SIMD एक्सटेंशन उपलब्ध हैं, तो यह नए लोगों के लिए संकलित हो सकता है, इसलिए प्रोग्रामर को कुछ भी बदलने की आवश्यकता नहीं है। या अगर यह बड़े कैश का लाभ उठाने या कैश मिस को कम करने के लिए संचालन / डेटा की व्यवस्था कर सकता है
phuclv

@ LưuV LnhPhúc Chào! मुझे यह विश्वास करते हुए खुशी हो रही है, लेकिन अंतर यह है कि उदाहरण के लिए सीपीयू प्रकार या कैश आकार कुछ स्थिर हैं जो गणना के दौरान नहीं बदल रहे हैं, इसलिए आसानी से एक स्थैतिक संकलक द्वारा भी किया जा सकता है। कैश मिक्स OTOH बहुत गतिशील हैं।
मार्टिन बर्जर

12

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

कोड अनुकूलन निश्चित रूप से "शास्त्रीय" संकलक द्वारा किया जा सकता है, लेकिन मुख्य अंतर पर ध्यान दें: जेआईटी संकलक के पास रनटाइम पर डेटा तक पहुंच है। यह बहुत बड़ा लाभ है; इसका सही तरीके से दोहन करना मुश्किल हो सकता है, जाहिर है।

उदाहरण के लिए, इस तरह से कोड पर विचार करें:

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 में उपयोग किए जाने वाले अधिकांश अनुकूलन को खारिज कर दिया ; मुझे बताया गया है कि उन आशावादों ने जेआईटी के लिए बहुत कुछ करना मुश्किल बना दिया, और अंत में भोले संकलित कोड तेजी से भागे। जाओ पता लगाओ।


वैसे, प्रकार के क्षरण (उदाहरण के लिए जावा में जेनेरिक) की उपस्थिति में, जेआईटी वास्तव में नुकसान के प्रकार पर है।
राफेल

इसलिए संकलित भाषा के लिए रनटाइम अधिक जटिल है क्योंकि अनुकूलन करने के लिए रनटाइम वातावरण को डेटा एकत्र करना होगा।
सादतमे

2
कई मामलों में, एक जेआईटी 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...}
सुपरकट

1
मैं @supercat से सहमत हूं और लगता है कि आपका उदाहरण वास्तव में बहुत भ्रामक है। केवल अगर k=0 हमेशा , मतलब यह इनपुट या पर्यावरण का कार्य नहीं है, क्या परीक्षण को गिराना सुरक्षित है - लेकिन यह निर्धारित करने के लिए स्थैतिक विश्लेषण की आवश्यकता होती है, जो बहुत महंगा है और इस प्रकार केवल संकलन समय पर सस्ती है। एक JIT तब जीत सकती है जब कोड के एक ब्लॉक के माध्यम से एक रास्ता दूसरों की तुलना में अधिक बार लिया जाता है, और इस पथ के लिए विशेष कोड का एक संस्करण बहुत तेज होगा। लेकिन जेआईटी अभी भी यह जांचने के लिए परीक्षण करेगी कि क्या तेज़ रास्ता लागू होता है , और यदि नहीं तो "धीमा रास्ता" अपनाएं।
j_random_hacker

एक उदाहरण: एक फ़ंक्शन एक Base* pपैरामीटर लेता है , और इसके माध्यम से वर्चुअल फ़ंक्शन कॉल करता है; रनटाइम विश्लेषण से पता चलता है कि हमेशा (या लगभग हमेशा) इंगित की गई वास्तविक वस्तु Derived1प्रकार की लगती है । JIT Derived1विधियों को स्टेटिकली सॉल्व्ड (या इनबिल्ड) कॉल के साथ फंक्शन का एक नया वर्जन तैयार कर सकता है। यह कोड एक सशर्त से पहले होगा जो यह जाँचता है कि क्या pअपेक्षित Derived1तालिका के लिए संभावित सूचक इंगित करता है ; यदि नहीं, तो यह इसके धीमे गतिशील तरीके से हल किए गए कॉल के साथ फ़ंक्शन के मूल संस्करण में कूदता है।
j_random_hacker
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.