C ++ संकलन में इतना समय क्यों लगता है?


540

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

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


58
VC ++ पूर्वनिर्धारित हेडर का समर्थन करता है। उनका उपयोग करने से मदद मिलेगी। बहुत।
ब्रायन

1
मेरे मामले में हाँ (ज्यादातर कुछ वर्गों के साथ - कोई टेम्पलेट नहीं) पहले से तैयार हेडर की गति लगभग 10x है
लोथर

@ ब्रायन मैं एक पुस्तकालय में एक पूर्व संकलित प्रमुख का उपयोग कभी नहीं करूंगा
कोल जॉनसन

13
It takes significantly longer to compile a C++ file- 1 सेकंड की तुलना में क्या आपका मतलब 2 सेकंड है? निश्चित रूप से यह दोगुना है, लेकिन शायद ही महत्वपूर्ण है। या 5 सेकंड की तुलना में आपका मतलब 10 मिनट है? कृपया मात्रा निर्धारित करें।
निक गैमन

2
मैंने मॉड्यूल पर अपना दांव लगाया; मुझे उम्मीद नहीं है कि C ++ प्रोजेक्ट्स अन्य प्रोग्रामिंग लैंग्वेज की तुलना में तेजी से बनते हैं, जो सिर्फ मॉड्यूल के साथ करते हैं, लेकिन यह कुछ प्रबंधन के साथ अधिकांश प्रोजेक्ट्स के लिए वास्तव में बंद हो सकता है। मुझे मॉड्यूल्स के बाद आर्टिफैक्ट इंटीग्रेशन के साथ एक अच्छा पैकेज मैनेजर देखने की उम्मीद है
अब्दुर्रहीम

जवाबों:


800

कई कारण

हैडर फाइलें

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

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

लिंक करना

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

पदच्छेद

वाक्य-विन्यास बेहद जटिल है, छंद पर निर्भर करता है, संदर्भ पर बहुत अधिक निर्भर करता है, और अवहेलना करने के लिए बहुत कठिन है। इसमें बहुत समय लगता है।

टेम्पलेट्स

C # में, List<T>केवल एक ही प्रकार है जो संकलित किया जाता है, फिर चाहे आपके कार्यक्रम में आपके पास कितनी भी सूची हो। C ++ में, vector<int>से एक पूरी तरह से अलग प्रकार है vector<float>, और प्रत्येक को अलग से संकलित करना होगा।

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

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

अनुकूलन

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

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

मशीन

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

निष्कर्ष

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


38
बिंदु 3 के बारे में: सी संकलन सी ++ की तुलना में अधिक तेज है। यह निश्चित रूप से दृश्यपटल है जो मंदी का कारण बनता है, और कोड पीढ़ी नहीं।
टॉम

72
टेम्प्लेट के बारे में: न केवल वेक्टर <int> वेक्टर से अलग से संकलित किया जाना चाहिए <डबल>, लेकिन वेक्टर <int> प्रत्येक संकलन इकाई में recompiled है जो इसका उपयोग करता है। लिंकर द्वारा निरर्थक परिभाषाओं को समाप्त कर दिया जाता है।
डेविड रोड्रिगेज -

15
dribeas: सच है, लेकिन यह टेम्प्लेट के लिए विशिष्ट नहीं है। इनलाइन फ़ंक्शंस या हेडर में परिभाषित कुछ अन्य चीज़ों को हर जगह फिर से जोड़ दिया जाएगा। लेकिन हाँ, यह खासतौर पर टेम्पलेट्स के साथ दर्दनाक है। :)
१५:०५ पर जलफ

15
@configurator: विजुअल स्टूडियो और जीसीसी दोनों प्री-कंपाइल हेडर के लिए अनुमति देते हैं, जो संकलन के लिए कुछ गंभीर गति-अप ला सकते हैं।
small_duck

5
सुनिश्चित नहीं है कि अनुकूलन समस्या है, क्योंकि हमारे DEBUG बिल्ड वास्तव में रिलीज़ मोड से धीमी है। Pdb पीढ़ी भी एक अपराधी है।
Gast128

40

मंदी अनिवार्य रूप से किसी भी संकलक के साथ समान नहीं है।

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

दो मुख्य अंतर एक बहुत मजबूत मॉड्यूल प्रणाली और एक सिंटैक्स थे जो एकल-पास संकलन की अनुमति देते थे।

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

इसके अलावा, आप देखेंगे कि आम तौर पर मेकफाइल्स की स्थापना की जाती है ताकि हर फ़ाइल को C में अलग से संकलित किया जाए, इसलिए यदि 10 स्रोत फ़ाइलों में सभी समान फ़ाइल का उपयोग करते हैं, तो उस फ़ाइल को 10 बार संसाधित किया जाता है।


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

1
@DietrichEpp अनुभववाद भुगतान करता है।
टॉमस जुबिरी

39

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

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


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

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

6
यदि पूरी हेडर फ़ाइल (संभावित टिप्पणियों और खाली लाइनों को छोड़कर) हेडर गार्ड के भीतर है, तो gcc फ़ाइल को याद रखने और सही प्रतीक को परिभाषित करने पर इसे छोड़ देने में सक्षम है।
सीजरबी

11
पार्स करना बड़ी बात है। एन-जोड़े के लिए समान आकार के स्रोत / हेडर फ़ाइलों में अन्योन्याश्रितियों के साथ, ओ (एन ^ 2) हेडर फ़ाइलों के माध्यम से गुजरता है। एक ही फाइल में सभी पाठ डालने से उस डुप्लिकेट पार्सिंग में कटौती हो रही है।
टॉम

9
छोटा पक्ष ध्यान दें: प्रति इकाई कई पार्सिंग के खिलाफ गार्ड गार्ड शामिल करें। समग्र रूप से कई पार्सिंग के खिलाफ नहीं।
मार्को वैन डे वोर्ट

16

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

इन्हें भी देखें: C ++ अक्सर पूछे जाने वाले प्रश्न


मुझे लगता है कि आपको अपने उत्तर के इस महत्वपूर्ण हिस्से को इंगित करने के लिए पहले से तैयार हेडर पर टिप्पणी को बोल्ड करना चाहिए।
केविन

6
यदि पूरी हेडर फ़ाइल (संभावित टिप्पणियों और खाली लाइनों को छोड़कर) हेडर गार्ड के भीतर है, तो gcc फ़ाइल को याद रखने और सही प्रतीक को परिभाषित करने पर इसे छोड़ देने में सक्षम है।
सीजरबी

5
@ सीजरबी: इसे अभी भी एक बार पूर्ण संकलन इकाई (.cpp फ़ाइल) के अनुसार संसाधित करना है।
सैम हैरवेल

16

C ++ को मशीन कोड में संकलित किया गया है। इसलिए आपके पास प्री-प्रोसेसर, कंपाइलर, ऑप्टिमाइज़र और अंत में असेंबलर है, जिसे सभी को चलाना होगा।

जावा और C # को बाइट-कोड / IL में संकलित किया गया है, और निष्पादन से पहले जावा वर्चुअल मशीन / .NET फ्रेमवर्क निष्पादित (या मशीन कोड में JIT संकलित) किया जाता है।

पायथन एक व्याख्या की गई भाषा है जिसे बाइट-कोड में भी संकलित किया गया है।

मुझे यकीन है कि इसके अन्य कारण भी हैं, लेकिन सामान्य तौर पर, देशी मशीन की भाषा को संकलित नहीं करने से समय की बचत होती है।


15
पूर्व प्रसंस्करण द्वारा जोड़ी गई लागत तुच्छ है। मंदी के लिए प्रमुख "अन्य कारण" यह है कि संकलन अलग-अलग कार्यों (एक प्रति फ़ाइल फ़ाइल) में विभाजित है, इसलिए आम हेडर बार-बार संसाधित होते हैं। यह O (N ^ 2) सबसे खराब स्थिति है, अधिकांश अन्य भाषाओं O (N) पार्सिंग समय।
टॉम

12
आप इसी तर्क से बता सकते हैं कि C, पास्कल आदि कंपाइलर धीमे हैं, जो औसतन सही नहीं है। यह C ++ के व्याकरण और विशाल राज्य के साथ करने के लिए अधिक है जिसे C ++ कंपाइलर को बनाए रखना है।
सेबस्टियन मच

2
C धीमा है। यह एक ही हेडर पार्सिंग समस्या से ग्रस्त है जैसा कि स्वीकृत समाधान है। उदाहरण के लिए एक साधारण विंडोज़ GUI प्रोग्राम लें, जिसमें कुछ संकलन इकाई में windows.h शामिल है, और संकलन प्रदर्शन को मापें जैसा कि आप (लघु) संकलन इकाइयों को जोड़ते हैं।
मार्को वैन डे वोर्ट

13

सबसे बड़े मुद्दे हैं:

1) अनंत हेडर रिपार्सिंग। पहले ही उल्लेख किया। शमन (जैसे # प्रागमा एक बार) आमतौर पर प्रति संकलन इकाई के अनुसार काम करते हैं, न कि प्रति निर्माण।

2) यह तथ्य है कि टूलचैन को अक्सर कई बायनेरिज़ (मेक, प्रीप्रोसेसर, कंपाइलर, असेम्बलर, इम्पेर्ड, इंडीडेफ़, लिंकर और डोलटूल इन एक्सट्रीम केस) में अलग किया जाता है, जिसमें सभी को प्रत्येक इनवोकेशन के लिए हर समय सभी राज्य को पुन: व्यवस्थित और पुनः लोड करना होता है ( संकलक, कोडांतरक) या फ़ाइलों के प्रत्येक जोड़े (संग्रहकर्ता, लिंकर और dlltool)।

यह भी देखें comp.compilers पर इस चर्चा: http://compilers.iecc.com/comparch/article/03-11-078 विशेष रूप से यह एक:

http://compilers.iecc.com/comparch/article/02-07-128

ध्यान दें कि जॉन, comp.compilers के मध्यस्थ सहमत हैं, और इसका मतलब यह है कि सी के लिए भी इसी तरह की गति प्राप्त करना संभव है, अगर कोई पूरी तरह से टूलकिन को एकीकृत करता है और हेडर प्री -प्लेस्ड लागू करता है। कई वाणिज्यिक सी कंपाइलर कुछ हद तक ऐसा करते हैं।

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


12

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

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

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

अब हम प्रत्येक चरण पर और अधिक विस्तार से ध्यान केंद्रित करेंगे कि वे कैसे तेजी से बनाए जा सकते हैं।

विन्यास

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

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

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

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

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

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

निर्भरता की जाँच

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

संकलन

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

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

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

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


9

एक संकलित भाषा हमेशा एक व्याख्या की गई भाषा की तुलना में बड़े प्रारंभिक ओवरहेड की आवश्यकता होती है। इसके अलावा, शायद आपने अपने C ++ कोड को बहुत अच्छी तरह से स्ट्रक्चर नहीं किया है। उदाहरण के लिए:

#include "BigClass.h"

class SmallClass
{
   BigClass m_bigClass;
}

की तुलना में बहुत धीमा संकलन:

class BigClass;

class SmallClass
{
   BigClass* m_bigClass;
}

3
विशेष रूप से सच है अगर BigClass में 5 और फ़ाइलों को शामिल करना शामिल है जो इसका उपयोग करता है, अंततः आपके प्रोग्राम के सभी कोड को शामिल करता है।
टॉम लेय्स

7
यह शायद एक कारण है। लेकिन उदाहरण के लिए पास्कल बस संकलन समय का दसवां हिस्सा लेता है जो एक समान C ++ प्रोग्राम लेता है। ऐसा इसलिए नहीं है क्योंकि gcc: s ऑप्टिमाइज़ेशन में अधिक समय लगता है, बल्कि यह कि पास्कल को पार्स करना आसान है और प्रीप्रोसेसर से निपटना नहीं है। डिजिटल मंगल डी कंपाइलर भी देखें।
डैनियल ओ

2
यह आसान पार्सिंग नहीं है, यह प्रतिरूपकता है जो प्रत्येक संकलन इकाई के लिए windows.h और umpteen अन्य हेडर को पुन: व्यवस्थित करने से बचती है। हां, पास्कल आसान होता है (हालांकि परिपक्व होते हैं, जैसे डेल्फी फिर से अधिक जटिल होते हैं), लेकिन यह वह नहीं है जो बड़ा अंतर करता है।
मार्को वैन डे वोइट

1
यहां दिखाई गई तकनीक जो संकलन गति में सुधार प्रदान करती है, को आगे की घोषणा के रूप में जाना जाता है ।
डेविडआरआर

केवल एक फ़ाइल में कक्षाएं लिखना। यह गन्दा कोड नहीं होगा?
फेनेकिन

7

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

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

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

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


3
मैं इस पद्धति पर आपत्ति को देखने में विफल हूं। यह मानते हुए कि आप स्क्रिप्ट या मेकफाइल से शामिल हैं, यह रखरखाव की समस्या नहीं है। यह वास्तव में संकलन मुद्दों को बिना किसी गति के संकलन को गति देता है। आप संकलन पर स्मृति खपत का तर्क दे सकते हैं, लेकिन यह आधुनिक मशीन पर शायद ही कोई मुद्दा है। तो इस दृष्टिकोण का क्या उद्देश्य है (यह दावा गलत है कि यह गलत है)?
राइलेबर्टन

9
@rileyberton (जब से किसी ने आपकी टिप्पणी को रद्द किया है) मुझे इसे वर्तनी दें: नहीं यह संकलन को गति नहीं देता है। वास्तव में, यह सुनिश्चित करें कि किसी भी संकलन लेता है बनाता है समय की अधिकतम राशि से नहीं अनुवाद इकाइयों को अलग। उनके बारे में महान बात यह है कि आप, है नहीं है सभी सीपीपी-s पुन: संयोजित करने के लिए अगर वे परिवर्तन नहीं किया की जरूरत है। (यह शैलीगत तर्कों की अवहेलना है)। उचित निर्भरता प्रबंधन और शायद पहले से तैयार हेडर बहुत बेहतर हैं।
sehe

7
क्षमा करें, लेकिन यह संकलन को गति देने के लिए एक बहुत ही कुशल तरीका हो सकता है, क्योंकि आप (1) लिंकिंग को बहुत अधिक समाप्त कर देते हैं, और (2) केवल एक बार उपयोग किए जाने वाले हेडर को संसाधित करना होता है। इसके अलावा, यह व्यवहार में काम करता है , अगर आप इसे आज़माने के लिए परेशान हैं। दुर्भाग्य से, यह वृद्धिशील पुनर्निर्माण को असंभव बनाता है, इसलिए हर निर्माण पूरी तरह से खरोंच से है। लेकिन एक पूर्ण इस विधि के साथ फिर से बनाना है बहुत तेजी से क्या आप अन्यथा मिल चाहते हैं उससे अधिक
jalf

4
@BartekBanachewicz यकीन है, लेकिन आपने जो कहा था कि "यह संकलन को गति नहीं देता है", बिना किसी क्वालीफायर के। जैसा कि आपने कहा, यह प्रत्येक संकलन को अधिकतम समय (कोई आंशिक पुनर्खरीद) लेने में सक्षम बनाता है, लेकिन साथ ही, यह नाटकीय रूप से अधिकतम को कम कर देता है, जिसकी तुलना में यह अन्यथा होगा। मैं सिर्फ यह कह रहा हूं कि "यह मत करो" की तुलना में यह थोड़ा अधिक बारीक है
जॅलफ

2
स्थिर चर और कार्यों के साथ मज़े करो। अगर मुझे एक बड़ी संकलन इकाई चाहिए, तो मैं एक बड़ी .cpp फ़ाइल बनाऊंगा।
gnasher729

6

कुछ कारण हैं:

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

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


5

आप जो व्यापार बंद कर रहे हैं, वह यह है कि कार्यक्रम तेजी से थोड़ा सा चलता है। विकास के दौरान यह आपके लिए एक ठंडा आराम हो सकता है, लेकिन विकास पूरा होने के बाद यह बहुत बड़ी बात हो सकती है, और यह कार्यक्रम केवल उपयोगकर्ताओं द्वारा चलाया जा रहा है।


3

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


3

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

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

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.