c++ प्रोग्राम - सी ++ संकलन इतना लंबा क्यों लेता है?




7 Answers

कई कारण:

  • शीर्षलेख फाइलें: प्रत्येक एकल संकलन इकाई को सैकड़ों या हजारों हेडर की आवश्यकता होती है 1: लोड किया गया, और 2: संकलित। उनमें से प्रत्येक को आम तौर पर प्रत्येक संकलन इकाई के लिए पुन: संकलित किया जाना चाहिए, क्योंकि प्रीप्रोसेसर यह सुनिश्चित करता है कि प्रत्येक संकलन इकाई के बीच हेडर संकलित करने का नतीजा भिन्न हो सकता है। (एक मैक्रो को एक संकलन इकाई में परिभाषित किया जा सकता है जो शीर्षलेख की सामग्री को बदलता है)।

    यह शायद मुख्य कारण है, क्योंकि इसमें प्रत्येक संकलन इकाई के लिए संकलित करने के लिए बड़ी मात्रा में कोड की आवश्यकता होती है, और इसके अतिरिक्त, प्रत्येक शीर्षलेख को कई बार संकलित किया जाना चाहिए (एक बार प्रत्येक संकलन इकाई जिसमें इसे शामिल किया जाता है)

  • लिंकिंग: एक बार संकलित हो जाने पर, सभी ऑब्जेक्ट फ़ाइलों को एक साथ जोड़ा जाना चाहिए। यह मूल रूप से एक मोनोलिथिक प्रक्रिया है जिसे समानांतर नहीं किया जा सकता है, और आपको अपनी पूरी परियोजना को संसाधित करना होगा।

  • पार्सिंग: वाक्यविन्यास पार्स के लिए बेहद जटिल है, संदर्भ पर भारी निर्भर करता है, और असंतोष करना बहुत मुश्किल है। इसमें बहुत समय लगता है

  • टेम्पलेट्स: सी # में, List<T> संकलित एकमात्र प्रकार है, इससे कोई फर्क नहीं पड़ता कि आपके प्रोग्राम में आपके पास कितनी तात्कालिकता है। सी ++ में, vector<int> vector<float> से एक पूरी तरह से अलग प्रकार है, और प्रत्येक को अलग से संकलित करना होगा।

    इसमें जोड़ें कि टेम्पलेट्स पूर्ण ट्यूरिंग-पूर्ण "उप-भाषा" बनाते हैं जिसे संकलक को समझना पड़ता है, और यह हास्यास्पद रूप से जटिल हो सकता है। यहां तक ​​कि अपेक्षाकृत सरल टेम्पलेट मेटाप्रोग्रामिंग कोड रिकर्सिव टेम्पलेट्स को परिभाषित कर सकता है जो दर्जनों और दर्जनों टेम्पलेट इंस्टेंटेशन बनाते हैं। टेम्पलेट्स का परिणाम बेहद जटिल प्रकारों में हो सकता है, हास्यास्पद रूप से लंबे नामों के साथ, लिंकर को बहुत अधिक अतिरिक्त काम जोड़ना। (इसे कई प्रतीकों के नामों की तुलना करना है, और यदि ये नाम कई हज़ार वर्णों में बढ़ सकते हैं, जो काफी महंगा हो सकता है)।

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

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

    इसके अलावा, एक सी ++ प्रोग्राम संकलक द्वारा पूरी तरह से अनुकूलित किया जाना चाहिए। एसी # प्रोग्राम भार-समय पर अतिरिक्त अनुकूलन करने के लिए जेआईटी कंपाइलर पर भरोसा कर सकता है, सी ++ को ऐसी कोई "दूसरी संभावना" नहीं मिलती है। कंपाइलर जेनरेट्स को अनुकूलित करने के रूप में अनुकूलित किया गया है।

  • मशीन कोड: सी ++ मशीन कोड में संकलित किया गया है जो बाइटकोड जावा या .NET उपयोग (विशेष रूप से x86 के मामले में) से कुछ अधिक जटिल हो सकता है।
    (यह केवल पूर्णता से बाहर बताया गया है क्योंकि टिप्पणियों और इस तरह में इसका उल्लेख किया गया था। व्यावहारिक रूप से, इस चरण में कुल संकलन समय के एक छोटे से अंश से अधिक लेने की संभावना नहीं है।)

इनमें से अधिकतर कारक सी कोड द्वारा साझा किए जाते हैं, जो वास्तव में काफी कुशलता से संकलित होते हैं। पार्सिंग चरण सी ++ में बहुत अधिक जटिल है, और इसमें काफी समय लग सकता है, लेकिन मुख्य अपराधी शायद टेम्पलेट्स है। वे उपयोगी हैं, और सी ++ को एक और अधिक शक्तिशाली भाषा बनाते हैं, लेकिन वे संकलन गति के मामले में भी अपना टोल लेते हैं।

अंतर का

सी #+ फ़ाइल को संकलित करते समय सी # और जावा की तुलना में बहुत लंबा समय लगता है। एक सामान्य आकार पायथन स्क्रीप्ट चलाने के लिए सी ++ फ़ाइल को संकलित करने में काफी समय लगता है। मैं वर्तमान में वीसी ++ का उपयोग कर रहा हूं लेकिन यह किसी भी कंपाइलर के साथ समान है। ऐसा क्यों है?

दो कारणों से मैं सोच सकता था कि हेडर फाइलें लोड कर रही थीं और प्रीप्रोसेसर चला रही थीं, लेकिन ऐसा प्रतीत नहीं होता कि यह इतना लंबा क्यों लगता है।




पार्सिंग और कोड पीढ़ी वास्तव में तेजी से हैं। असली समस्या फाइलें खोलना और बंद करना है। याद रखें, यहां तक ​​कि गार्ड शामिल करने के साथ, कंपाइलर ने अभी भी। फ़ाइल खोल दी है, और प्रत्येक पंक्ति को पढ़ा है (और फिर इसे अनदेखा करें)।

एक दोस्त (एक बार काम पर ऊब गया), अपनी कंपनी के आवेदन ले लिया और सब कुछ डाल दिया - सभी स्रोत और हेडर फाइलें - एक बड़ी फाइल में। संकलन समय 3 घंटे से 7 मिनट तक गिर गया।




एक और कारण घोषणाओं का पता लगाने के लिए सी प्री-प्रोसेसर का उपयोग है। यहां तक ​​कि हेडर गार्ड के साथ भी, उन्हें अभी भी बार-बार पार्स किया जाना चाहिए, हर बार जब वे शामिल होते हैं। कुछ कंपाइलर्स प्री-कंपाइल हेडर का समर्थन करते हैं जो इससे मदद कर सकते हैं, लेकिन उनका हमेशा उपयोग नहीं किया जाता है।

यह भी देखें: सी ++ अक्सर पूछे जाने वाले उत्तर




बिल्डिंग सी / सी ++: वास्तव में क्या होता है और इसमें इतना समय क्यों लगता है

सॉफ्टवेयर विकास समय का एक अपेक्षाकृत बड़ा हिस्सा लेखन, दौड़ने, डिबगिंग या यहां तक ​​कि कोड को डिजाइन करने पर खर्च नहीं किया जाता है, लेकिन इसे संकलित करने के लिए प्रतीक्षा कर रहा है। चीजों को तेज़ी से बनाने के लिए, हमें पहले यह समझना होगा कि सी / सी ++ सॉफ़्टवेयर संकलित होने पर क्या हो रहा है। कदम इस प्रकार मोटे तौर पर हैं:

  • विन्यास
  • टूल स्टार्टअप बनाएं
  • निर्भरता जांच
  • संकलन
  • लिंक करना

अब हम प्रत्येक चरण को अधिक विस्तार से देखेंगे कि इस पर ध्यान केंद्रित किया जा रहा है कि उन्हें तेज़ी से कैसे बनाया जा सकता है।

विन्यास

निर्माण शुरू करने के लिए यह पहला कदम है। आमतौर पर एक कॉन्फ़िगर स्क्रिप्ट या सीएमके, Gyp, SCons या किसी अन्य उपकरण को चलाने का मतलब है। यह बहुत बड़ी Autotools- आधारित कॉन्फ़िगर स्क्रिप्ट के लिए एक सेकंड से कई मिनट तक कुछ भी ले सकता है।

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

टूल स्टार्टअप बनाएं

यह तब होता है जब आप आईडीई पर बिल्ड आइकन पर बनाते हैं या क्लिक करते हैं (जो आमतौर पर बनाने के लिए उपनाम होता है)। बिल्ड टूल बाइनरी शुरू होती है और इसकी कॉन्फ़िगरेशन फ़ाइलों के साथ-साथ बिल्ड कॉन्फ़िगरेशन भी पढ़ती है, जो आम तौर पर एक ही चीज़ होती है।

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

यह ध्यान दिया जाना चाहिए कि कारण इतना धीमा है कि कार्यान्वयन बग नहीं है। मेकफ़ाइल के सिंटैक्स में कुछ क्विर्क हैं जो वास्तव में तेज़ कार्यान्वयन को असंभव बनाते हैं। अगले चरण के साथ संयुक्त होने पर यह समस्या और भी ध्यान देने योग्य है।

निर्भरता जांच

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

संकलन

इस बिंदु पर हम अंततः संकलक का आह्वान करते हैं। कुछ कोनों को काटना, यहां अनुमानित कदम हैं।

  • विलय में शामिल हैं
  • कोड पार्सिंग
  • कोड जनरेशन / अनुकूलन

लोकप्रिय धारणा के विपरीत, सी ++ संकलन वास्तव में धीमा नहीं है। एसटीएल धीमा है और सी ++ संकलित करने के लिए उपयोग किए जाने वाले अधिकांश बिल्ड टूल्स धीमे होते हैं। हालांकि भाषा के धीमे हिस्सों को कम करने के तेज़ उपकरण और तरीके हैं।

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




कुछ कारण हैं:

1) सी ++ व्याकरण सी # या जावा से अधिक जटिल है और पार्स करने में अधिक समय लगता है।

2) (अधिक महत्वपूर्ण) सी ++ कंपाइलर मशीन कोड उत्पन्न करता है और संकलन के दौरान सभी अनुकूलन करता है। सी # और जावा सिर्फ आधे रास्ते पर जाते हैं और इन चरणों को जेआईटी में छोड़ देते हैं।




बड़ी सी ++ परियोजनाओं में संकलन समय को कम करने का एक आसान तरीका एक * .cpp फ़ाइल शामिल करना है जिसमें आपकी परियोजना में सभी सीपीपी फ़ाइलें शामिल हैं और संकलित करें। यह एक बार हेडर विस्फोट समस्या को कम कर देता है। इसका लाभ यह है कि संकलन त्रुटियां अभी भी सही फ़ाइल का संदर्भ लेंगी।

उदाहरण के लिए, मान लें कि आपके पास a.cpp, b.cpp और c.cpp है .. एक फ़ाइल बनाएं: everything.cpp:

#include "a.cpp"
#include "b.cpp"
#include "c.cpp"

फिर सब कुछ.cpp बनाकर प्रोजेक्ट संकलित करें




ऐसे दो मुद्दे हैं जिनके बारे में मैं सोच सकता हूं कि उस गति को प्रभावित कर सकता है जिस पर सी ++ में आपके प्रोग्राम संकलित हो रहे हैं।

संभावित अंक # 1 - हेडर को संकलित करना: (यह किसी अन्य उत्तर या टिप्पणी द्वारा पहले से ही संबोधित किया जा सकता है या नहीं।) माइक्रोसॉफ्ट विजुअल सी ++ (एकेए वीसी ++) प्रीकंपिल्ड हेडर का समर्थन करता है, जिसे मैं अत्यधिक अनुशंसा करता हूं। जब आप कोई नई प्रोजेक्ट बनाते हैं और आपके द्वारा बनाए जा रहे प्रोग्राम के प्रकार का चयन करते हैं, तो आपकी स्क्रीन पर एक सेटअप विज़ार्ड विंडो दिखाई देनी चाहिए। यदि आप इसके नीचे "अगला>" बटन दबाते हैं, तो विंडो आपको उस पृष्ठ पर ले जाएगी जिसमें सुविधाओं की कई सूचियां हैं; सुनिश्चित करें कि "प्रीकंपील्ड हेडर" विकल्प के बगल में स्थित बॉक्स चेक किया गया है। (नोट: यह C ++ में Win32 कंसोल अनुप्रयोगों के साथ मेरा अनुभव रहा है, लेकिन यह C ++ में सभी प्रकार के प्रोग्रामों के साथ मामला नहीं हो सकता है।)

संभावित अंक # 2 - इस स्थान पर संकलित किया जा रहा है: इस गर्मी में, मैंने एक प्रोग्रामिंग कोर्स लिया, और हमें अपनी सभी परियोजनाओं को 8 जीबी फ्लैश ड्राइव पर स्टोर करना पड़ा, क्योंकि प्रयोगशाला में कंप्यूटर हर रात मध्यरात्रि में मिटा दिए गए थे, जो हमारे सभी काम मिटा दिया होगा। यदि आप पोर्टेबिलिटी / सुरक्षा / आदि के लिए बाहरी स्टोरेज डिवाइस से संकलित कर रहे हैं, तो आपके प्रोग्राम को संकलित करने में बहुत लंबा समय लग सकता है (यहां तक ​​कि मैंने ऊपर वर्णित प्रीकंपिल्ड हेडर के साथ भी), विशेष रूप से यदि यह काफी बड़ा है कार्यक्रम। इस मामले में आपके लिए मेरी सलाह आपके द्वारा उपयोग किए जा रहे कंप्यूटर की हार्ड ड्राइव पर प्रोग्राम बनाना और संकलित करना होगा, और जब भी आप चाहें / किसी भी कारण से अपनी परियोजना (ओं) पर काम करना बंद करना चाहते हैं, तो उन्हें अपने बाहरी स्थान पर स्थानांतरित करें स्टोरेज डिवाइस, और फिर "सुरक्षित रूप से हार्डवेयर निकालें और मीडिया निकालें" आइकन पर क्लिक करें, जो उस पर डिस्कनेक्ट करने के लिए एक छोटे से चेक सर्कल के साथ एक छोटे से हरे रंग के सर्कल के पीछे एक छोटी फ्लैश ड्राइव के रूप में दिखाई देनी चाहिए।

मैं आशा करता हूं कि इससे तुम्हें सहायता मिलेगी; अगर यह करता है तो मुझे बताएं! :)




Related

c++ performance compilation