2009-02-08 13 views
6

मैं अपने अगले प्रोजेक्ट में मैनेजर मेमोरी के बारे में कुछ समय के लिए सोच रहा था। जो सी/सी ++ में डीएसएल लिख रहा है।कचरा एकत्रित सी सी ++ से तेज हो जाएगा?

यह तीन तरीकों से किया जा सकता है।

  1. संदर्भ गणना सी या सी ++।
  2. कचरा इकट्ठा सी
  3. सी ++ में, स्टैक से वर्ग और संरचनाओं को प्रतिलिपि बनाने और किसी प्रकार के जीसी के साथ अलग-अलग तारों को प्रबंधित करने के लिए प्रतिलिपि बनाना।

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

एक संबंधित पक्ष प्रश्न। प्रोग्राम की शुरुआत में एक बड़ा हिस्सा आवंटित करने और इसके ऊपर अपना स्वयं का मेमोरी मैनेजर चलाने से धीमा हो जाएगा? .NET ऐसा लगता है। लेकिन मैं उलझन में हूं कि हम इस काम को बेहतर और तेज करने के लिए ओएस पर क्यों नहीं भरोसा कर सकते हैं जो हम खुद कर सकते हैं।

उत्तर

8

यह सब निर्भर करता है! यह एक सुंदर खुला सवाल है। इसका जवाब देने के लिए इसे निबंध की जरूरत है!

अरे .. यहाँ एक ने किसी को पहले तैयार है:

http://lambda-the-ultimate.org/node/2552

http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html

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

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

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

+0

क्या आप कह रहे हैं कि यह सब * भाषा *, सी या सी ++ के आधार पर होगा, कोई उपयोग करता है? चूंकि इनमें से किसी भी भाषा में, किसी को जीसी स्वयं को लागू करना है, मुझे लगता है कि प्रति प्रतिरूप भिन्नता नहीं है, केवल प्रति एल्गोरिदम भिन्नता है। –

+0

पूरी तरह से सुनिश्चित नहीं है कि आप क्या पूछ रहे हैं। लेकिन, एक ही स्मृति प्रबंधन एल्गोरिदम दोनों भाषाओं पर लागू किया जा सकता है। हालांकि सी ++ में आप ऑपरेटर को ओवरराइड करने की तरह कुछ करेंगे और इसे लागू करने के लिए हटा देंगे। सी में मुझे यकीन नहीं है; संभवतः अपने कार्यों का नाम दें और सभी आवंटन के लिए उनका उपयोग सुनिश्चित करें। –

4

उह ... यह निर्भर करता है कि आप अपने डीएसएल के लिए कचरा संग्रहण प्रणाली लिखें। न तो सी या सी ++ अंतर्निहित कचरा संग्रहण सुविधा के साथ आता है लेकिन या तो इसका उपयोग बहुत ही कुशल या बहुत अक्षम कचरा कलेक्टर लिखने के लिए किया जा सकता है। वैसे, ऐसी चीज लिखना, एक गैर-तुच्छ कार्य है।

डीएसएल अक्सर रूबी या पायथन जैसे उच्च स्तर की भाषाओं में लिखे जाते हैं क्योंकि भाषा लेखक कचरा संग्रह और भाषा की अन्य सुविधाओं का लाभ उठा सकते हैं। सी और सी ++ पूर्ण, औद्योगिक ताकत भाषाओं को लिखने के लिए बहुत अच्छे हैं, लेकिन आपको निश्चित रूप से यह जानने की ज़रूरत है कि आप उनका उपयोग करने के लिए क्या कर रहे हैं - yacc का ज्ञान और लेक्स विशेष रूप से उपयोगी है लेकिन dynamic memory management की अच्छी समझ भी महत्वपूर्ण है, जैसा कि आप कहते हैं। यदि आप अभी भी सी/सी ++ में डीएसएल के विचार को पसंद करते हैं, तो आप keykit, सी में लिखे ओपन सोर्स संगीत डीएसएल को भी देख सकते हैं।

1

संबंधित पक्ष प्रश्न। कार्यक्रम की शुरुआत में एक बड़ा चक आवंटित करने से धीमा हो जाएगा और इस पर अपना खुद का मेमोरी मैनेजर चलाएगा? .NET ऐसा लगता है। लेकिन मैं उलझन में हूं कि हम इस काम को बेहतर और तेज करने के लिए ओएस पर क्यों नहीं भरोसा कर सकते हैं जो हम खुद कर सकते हैं।

ओएस को स्मृति आवंटन को संभालने के साथ समस्या यह है कि यह अनिश्चित व्यवहार का परिचय देता है। प्रोग्रामर के बारे में जानने का कोई तरीका नहीं है कि ओएस मेमोरी का एक नया हिस्सा वापस करने के लिए कितना समय लगेगा - अगर डिस्क पर मेमोरी को पग किया जाए तो आवंटन काफी महंगा हो सकता है।

इसलिए को रोकना एक अच्छा विचार हो सकता है, खासकर जब एक प्रतिलिपि कचरा कलेक्टर का उपयोग करते समय। यह स्मृति खपत में वृद्धि करेगा, लेकिन आवंटन तेजी से होगा क्योंकि ज्यादातर मामलों में यह केवल सूचक वृद्धि होगी।

+0

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

+0

मेमोरी को पढ़ना/लिखना जो पहले ही आवंटित किया गया है, यह भी काफी महंगा हो सकता है अगर इसे डिस्क पर निकाल दिया गया हो। :) – bk1e

3

अधिकांश कचरा संग्रहण कार्यान्वयन के साथ, आवंटन में गति सुधार दिखाई दे सकता है, लेकिन फिर आपके पास संग्रह चरण की अतिरिक्त लागत है जिसे आपके प्रोग्राम के निष्पादन में किसी भी बिंदु पर ट्रिगर किया जा सकता है, जिससे अचानक (प्रतीत होता है यादृच्छिक) देरी हो जाती है।

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

4

कचरा एकत्रित क्यों सी सी ++ से तेज होगा? सी के लिए उपलब्ध एकमात्र कचरा कलेक्टर बहुत अक्षम चीजें हैं, जो वास्तव में आपके कोड की गुणवत्ता में सुधार करने के बजाय मेमोरी लीक प्लग करने के लिए डिज़ाइन किए गए हैं।

किसी भी मामले में, सी ++ में कम कोड के साथ बेहतर प्रदर्शन तक पहुंचने की क्षमता है (ध्यान दें कि यह केवल एक संभावित है। सी ++ कोड लिखना भी बहुत संभव है जो समकक्ष सी से बहुत धीमी है)।

दोनों भाषाओं की वर्तमान स्थिति को ध्यान में रखते हुए, जीसी वर्तमान में आपके कोड में प्रदर्शन को बेहतर बनाने के लिए नहीं जा रहे हैं। जीसी को इसके लिए डिजाइन की गई भाषाओं में बहुत ही कुशल बनाया जा सकता है। सी/सी ++ उनमें से नहीं हैं। ;)

इसके अलावा, यह कहना असंभव है। भाषाओं में गति नहीं है। यह समझने में कोई फर्क नहीं पड़ता कि कौन सी भाषा तेज है। यह 1) पर निर्भर करता है विशिष्ट कोड, 2) संकलक जो इसे संकलित करता है, और 3) जिस प्रणाली पर यह चल रहा है (हार्डवेयर और साथ ही ओएस)।

malloc .NET समकक्षों की तुलना में बहुत धीमी गति से संचालन है, इसलिए हाँ, यदि आप बहुत से छोटे आवंटन कर रहे हैं, तो आप एक बार स्मृति के बड़े पूल को आवंटित करने से बेहतर हो सकते हैं, और उसके बाद भाग का उपयोग कर सकते हैं उस।

कारण यह है कि ओएस को सभी मुक्त मेमोरी क्षेत्रों की एक लिंक की गई सूची का पालन करके स्मृति का एक मुक्त हिस्सा मिलना है। .NET में, एक नया() कॉल मूल रूप से आवंटन द्वारा आवश्यक कई बाइट्स के रूप में हीप पॉइंटर को स्थानांतरित करने से कहीं अधिक नहीं है।

0

न तो सी और न ही सी ++ आपको कचरा मुफ्त में देगा। वे आपको क्या देंगे स्मृति आवंटन पुस्तकालय (जो मॉलोक/फ्री, आदि प्रदान करते हैं)। कचरा संग्रहण पुस्तकालय लिखने के लिए एल्गोरिदम के लिए कई ऑनलाइन संसाधन हैं। एक अच्छी शुरुआत link text

0

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

डी प्रोग्रामिंग भाषा एक कचरा एकत्रित भाषा है और एबीआई सी के साथ संगत है और आंशिक रूप से एबीआई सी ++ के साथ संगत है। This Page सी ++ और डी

1

जैसा कि लोगों ने इंगित किया है - जीसी आवंटित करने के लिए तेज़ है (क्योंकि यह आपको इसकी सूची में अगला ब्लॉक देता है), लेकिन कुल मिलाकर धीमा है (क्योंकि इसे कॉम्पैक्ट करना है) आवंटन तेजी से होने के क्रम में नियमित रूप से ढेर)।

तो - समझौता समाधान के लिए जाना (जो वास्तव में बहुत बहुत अच्छी है):

आप अपनी खुद की ढेर, आप आम तौर पर आवंटित वस्तु के प्रत्येक आकार के लिए एक (या बनाने के 4 बाइट, 8 बाइट, 16- बाइट, 32-बाइट, इत्यादि) फिर, जब आप स्मृति का एक नया टुकड़ा चाहते हैं तो आप उपयुक्त ढेर पर अंतिम 'ब्लॉक' पकड़ लेंगे। चूंकि आप इन ढेर से पूर्व-आवंटित करते हैं, इसलिए आवंटित होने पर आपको केवल अगली नि: शुल्क ब्लॉक पकड़नी होगी। यह मानक आवंटन से बेहतर काम करता है क्योंकि आप खुशी से स्मृति बर्बाद कर रहे हैं - यदि आप 12 बाइट आवंटित करना चाहते हैं, तो आप 16-बाइट ढेर से एक संपूर्ण 16 बाइट ब्लॉक छोड़ देंगे। आप प्रयुक्त वी मुक्त ब्लॉकों का बिटमैप रखते हैं ताकि आप स्मृति के भार को बर्बाद किए बिना या कॉम्पैक्ट की आवश्यकता के बिना तुरंत आवंटित कर सकें।

इसके अलावा, क्योंकि आप कई ढेर चला रहे हैं, अत्यधिक समानांतर सिस्टम बहुत बेहतर काम करते हैं क्योंकि आपको अक्सर लॉक करने की आवश्यकता नहीं होती है (यानी आपके पास प्रत्येक ढेर के लिए कई ताले हैं ताकि आपको लगभग उतना ही विवाद न हो)

इसे आज़माएं - हमने इसे मानक ढेर को बहुत गहन अनुप्रयोग पर बदलने के लिए उपयोग किया, प्रदर्शन काफी बढ़ गया।

बीटीडब्ल्यू। मानक आवंटकों धीमा होने का कारण यह है कि वे स्मृति को बर्बाद न करने का प्रयास करते हैं - इसलिए यदि आप मानक ढेर से 5 बाइट, 7 बाइट और 32 बाइट आवंटित करते हैं, तो यह उन 'सीमाओं' को बनाए रखेगा। अगली बार आपको आवंटित करने की आवश्यकता है, यह उन लोगों के माध्यम से चलेगा जो आपको पर्याप्त जानकारी देने के लिए पर्याप्त जगह की तलाश में हैं। यह कम-मेमोरी सिस्टम के लिए अच्छा काम करता है, लेकिन आपको केवल यह देखना होगा कि अधिकांश ऐप्स आज कितने मेमोरी का उपयोग करते हैं यह देखने के लिए कि जीसी सिस्टम दूसरी तरफ जाते हैं, और यथासंभव तेज़ी से आवंटन करने की कोशिश करते हैं, जबकि स्मृति की कितनी मेमोरी है व्यर्थ।

1

समस्या चर का एक बहुत है, लेकिन अगर आपके आवेदन को ध्यान में कचरा संग्रहण के साथ लिखा है, और अगर आप इस तरह है कि नहीं है ब्लॉकों के लिए अलग आवंटन कॉल के रूप में Boehm collector की विशेष सुविधाओं, शोषण पॉइंटर्स होते हैं, फिर सामान्य नियम के रूप में आपके आवेदन - सरल इंटरफ़ेस होगा - कुछ तेज़ी से चलाएगा - स्पष्ट स्मृति प्रबंधन का उपयोग करते हुए समान अनुप्रयोग की तुलना में 1.2x से 2x स्पेस की आवश्यकता होगी।

इन दावों का समर्थन करने वाले दस्तावेज और सबूत के लिए, आप रूहम की वेबसाइट पर जानकारी और रूढ़िवादी कचरा संग्रह की मापा लागत पर बेन जोर्न के कई कागजात देख सकते हैं।

सबसे महत्वपूर्ण बात यह है कि आप प्रयासों का एक टन बचाएंगे और स्मृति-प्रबंधन कीड़े के एक महत्वपूर्ण वर्ग के बारे में चिंता करने की आवश्यकता नहीं होगी।

सी बनाम सी ++ का मुद्दा ऑर्थोगोनल है, लेकिन जीसी संदर्भ गणना से निश्चित रूप से तेज़ होगा, खासकर जब संदर्भ गणना के लिए कोई कंपाइलर समर्थन नहीं है।

0

मेरा सुझाव है कि यदि आपने एक प्रोग्राम लिखा है जहां मेमोरी आवंटन और डेलोकेशन (स्पष्ट रूप से या जीसी'एड) बाधा है, तो आपको अपने आर्किटेक्चर, डिज़ाइन और कार्यान्वयन को फिर से सोचना चाहिए।

0

यदि आप स्पष्ट रूप से स्मृति का प्रबंधन नहीं करना चाहते हैं, तो सी/सी ++ का उपयोग न करें। संदर्भ गणना या कंपाइलर समर्थित कचरा कलेक्टरों के साथ बहुत सी भाषाएं हैं जो शायद आपके लिए बेहतर काम करती हैं।

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

मुझे पता है कि यह एक अच्छा विचार की तरह लगता है, लेकिन वास्तव में, आपको केवल उस कार्य को अधिक उपयुक्त भाषा लेना चाहिए।