स्कोप-आधारित स्मृति प्रबंधन के नुकसान


38

मैं वास्तव में गुंजाइश आधारित स्मृति प्रबंधन (SBMM), या की तरह आरए II , के रूप में यह है और अधिक सामान्यतः (भ्रमित करने वाले?) के लिए सी ++ समुदाय द्वारा भेजा। जहां तक ​​मुझे पता है, सी ++ (और सी) को छोड़कर, आज उपयोग में कोई अन्य मुख्यधारा की भाषा नहीं है जो एसबीएमएम / आरएआईआई को अपना मुख्य मेमोरी प्रबंधन तंत्र बनाती है, और इसके बजाय वे कचरा संग्रह (जीसी) का उपयोग करना पसंद करते हैं।

मैं यह नहीं बल्कि भ्रामक लगता है

  1. SBMM कार्यक्रमों को अधिक निर्धारक बनाता है (आप किसी वस्तु के नष्ट होने पर ठीक-ठीक बता सकते हैं);
  2. जीसी का उपयोग करने वाली भाषाओं में आपको अक्सर मैनुअल संसाधन प्रबंधन करना पड़ता है (उदाहरण के लिए, जावा में फाइलें बंद करना), जो आंशिक रूप से जीसी के उद्देश्य को पराजित करता है और त्रुटि प्रवण भी होता है;
  3. हीप मेमोरी भी (बहुत शान से, इमो) स्कोप-बाउंड हो सकती है ( std::shared_ptrसी ++ में देखें )।

SBMM का अधिक व्यापक रूप से उपयोग क्यों नहीं किया जाता है? इसके नुकसान क्या हैं?


1
कुछ नुकसान (विशेष रूप से गति से संबंधित) पर चर्चा की गई है: en.wikipedia.org/wiki/…
फिलिप

2
जावा की मैनुअल संसाधन प्रबंधन समस्या यह सुनिश्चित करने का एक पक्ष प्रभाव है कि finalize()कचरा संग्रहण से पहले किसी वस्तु की विधि को बुलाया जाएगा। वास्तव में, यह समस्या का एक ही वर्ग बनाता है जिसे कचरा संग्रह को हल करना है।
Blrfl

7
@ बेलर बकवास। "मैनुअल" संसाधन प्रबंधन (स्मृति के अलावा अन्य संसाधनों के लिए, जाहिर है) तब भी बेहतर होगा जब "समस्या" मौजूद नहीं थी, क्योंकि संसाधन अप्रयुक्त होने के बाद जीसी बहुत लंबे समय तक चल सकता है, या बिल्कुल भी नहीं चल सकता है। यह स्मृति के लिए कोई समस्या नहीं है , और स्मृति प्रबंधन यह है कि कचरा संग्रह को हल करना है।

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

जवाबों:


27

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

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

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

अब, आप कुछ डाउनसाइड को सभी मूल्यों को एकत्रित कचरा बनाने के लिए नाम देते हैं । हालाँकि, RAII के साथ मेमोरी-सुरक्षित GC और मान प्रकार दोनों को एक भाषा में एकीकृत करना बहुत कठिन है, इसलिए शायद इन ट्रेड ऑफ को अन्य माध्यमों से अलग करना बेहतर है?

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

आपका दूसरा बिंदु, मैनुअल संसाधन प्रबंधन, आजकल एक बयान के माध्यम से संबोधित किया जाता है जो स्कोप-आधारित क्लीनअप करता है, लेकिन इस क्लीन को ऑब्जेक्ट लाइफ टाइम (इसलिए जीसी और मेमोरी सुरक्षा के साथ बातचीत नहीं) करता है। यह हाल के जावा संस्करणों में पायथन में using, सी -में with, try-विथ-संसाधनों में है।


1
यह व्याख्या नहीं करता है कि क्यों जीसी जैसे nondeterministic मॉडल नियतात्मक लोगों से बेहतर होना चाहिए। usingबयान केवल स्थानीय रूप से संभव हैं। इस तरह सदस्य चर में आयोजित संसाधनों को साफ करना असंभव है।
फिलिप

8
सब कुछ के लिए @Philipp साझा स्वामित्व है एक जीसी, बस एक बहुत ही गरीब है। यदि आप गिनती को लागू करने के लिए "साझा स्वामित्व" लेते हैं, तो कृपया ऐसा कहें, लेकिन अमोन के जवाब पर टिप्पणियों में चक्र के बारे में चर्चा करते रहें। मुझे यह भी पता नहीं है कि क्या ओपी काउंटिंग इस मायने में निर्णायक है कि ओपी को इसमें दिलचस्पी है (ऑब्जेक्ट्स को जितनी जल्दी हो सके मुक्त कर दिया जाता है, साइकिल छूट रही है, लेकिन आप अक्सर यह नहीं बता सकते कि यह प्रोग्राम कब है)। इसके अलावा, सब कुछ के लिए रेफरी काउंटिंग धीमी, एक आधुनिक ट्रेसिंग जीसी की तुलना में बहुत धीमी है।

16
usingRAII की तुलना में एक मज़ाक है, तो बस आप जानते हैं।
डेडएमजी

3
@Philipp कृपया "बेहतर" के लिए अपने मीट्रिक का वर्णन करें। यह सच है कि स्मृति प्रबंधन से निपटने के लिए मैनुअल मेमोरी प्रबंधन रन-टाइम पर तेज है। हालाँकि सॉफ्टवेयर की लागत को केवल मेमोरी प्रबंधन पर खर्च किए गए सीपीयू समय पर विशुद्ध रूप से नहीं आंका जा सकता है।
ArTs

2
@ArTs: मैं जरूरी भी इस के साथ सहमत नहीं होगा। RAII इस आवश्यकता के साथ आता है कि किसी वस्तु को नष्ट होना चाहिए क्योंकि यह गुंजाइश छोड़ती है। एक लूप, तब, n ऑब्जेक्ट डिस्ट्रक्टेशन करने के लिए आवश्यक होता है। एक आधुनिक पीढ़ीगत जीसी के तहत, उन विनाशों को लूप के अंत तक या बाद में भी स्थगित किया जा सकता है, और स्मृति के सैकड़ों पुनरावृत्तियों को नष्ट करने के लिए सिर्फ एक ऑपरेशन करते हैं। एक जीसी अपने अच्छे मामलों में बहुत तेज हो सकता है।
फॉशी

14

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

कचरा एकत्र करने वाली भाषाएं सीधे RAII का उपयोग नहीं कर सकती हैं, लेकिन अक्सर एक समतुल्य प्रभाव के साथ वाक्य रचना प्रदान करती हैं। जावा में, हमारे पास कोशिश-साथ-बयान स्रोत है

try (BufferedReader br = new BufferedReader(new FileReader(path))) { ... }

जो स्वचालित रूप से .close()ब्लॉक निकास पर संसाधन पर कॉल करता है। C # में IDisposableइंटरफ़ेस है, जो .Dispose()एक using (...) { ... }स्टेटमेंट को छोड़ने पर कॉल करने की अनुमति देता है । अजगर का withकथन है:

with open(filename) as f:
    ...

जो इसी तरह से काम करता है। इस पर एक दिलचस्प स्पिन में, रूबी की फ़ाइल खुली विधि को कॉलबैक मिलता है। कॉलबैक निष्पादित होने के बाद, फ़ाइल बंद है।

File.open(name, mode) do |f|
    ...
end

मुझे लगता है कि Node.js उसी रणनीति का उपयोग करता है।


4
रूबी से बहुत पहले संसाधन प्रबंधन के लिए उच्च आदेश कार्यों का उपयोग करना। लिसप्स में, ऐसा कहना, with-open-filehandleकार्य करने के लिए काफी आम है, जो फ़ाइल को खोलता है, इसे एक फ़ंक्शन के लिए देता है और फ़ंक्शन के लौटने पर फ़ाइल को फिर से बंद कर देता है।
जॉर्ज डब्ल्यू मित्तग

4
चक्रीय संदर्भ तर्क काफी सामान्य है, लेकिन यह वास्तव में कितना महत्वपूर्ण है? यदि स्वामित्व स्पष्ट है, तो कमजोर बिंदुओं का उपयोग करके चक्रीय संदर्भों को कम किया जा सकता है।
फिलिप

2
@ फ़ीलिप जब आप रेफरी काउंटिंग का उपयोग करते हैं, तो स्वामित्व आमतौर पर स्पष्ट नहीं होता है। इसके अलावा, यह उत्तर उन भाषाओं के बारे में बात करता है, जो विशेष रूप से और स्वचालित रूप से Ref गिनती का उपयोग करती हैं, इसलिए कमजोर संदर्भ या तो मौजूद नहीं हैं या मजबूत संदर्भों की तुलना में उपयोग करने के लिए बहुत कठिन हैं।

3
जब तक आप जटिल ग्राफ़ के साथ काम नहीं कर रहे हैं, तब तक @Piplipp चक्रीय डेटा संरचना बहुत दुर्लभ हैं। कमजोर संकेत एक सामान्य चक्रीय वस्तु ग्राफ में मदद नहीं करते हैं, हालांकि वे एक पेड़ में माता-पिता की तरह सामान्य मामलों में मदद करते हैं। एक अच्छा समाधान एक संदर्भ वस्तु रखना है जो पूरे ग्राफ के संदर्भ का प्रतिनिधित्व करता है, और विनाश का प्रबंधन करता है। रिफ़काउंटिंग एक सौदा नहीं है, लेकिन इसके लिए आवश्यक है कि प्रोग्रामर अपने प्रतिबंधों के बारे में बहुत जागरूक हो। यानी यह GC की तुलना में थोड़ा अधिक संज्ञानात्मक लागत है।
अमोन

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

14

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

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

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


1
सुधार केवल रचना योग्य है यदि वस्तुएं केवल अपनी ओर से संदर्भ रखती हैं, न कि उन संदर्भों के लक्ष्यों की ओर से। एक बार जब सूचनाएँ मिक्स में प्रवेश करती हैं (बॉब जो का संदर्भ देता है क्योंकि जो ने बॉब से बॉब को सूचित करने के लिए कहा कि कब कुछ हुआ और बॉब ने ऐसा करने का वादा किया, लेकिन बॉब अन्यथा जो की परवाह नहीं करता है), जीसी शुद्धता को अक्सर स्कोप संसाधन प्रबंधन की आवश्यकता होती है [मैन्युअल रूप से कई मामलों में लागू किया गया है, क्योंकि जीसी सिस्टम में सी ++ के स्वचालन की कमी है]।
सुपरकैट

@ सुपरकैट: "जीसी शुद्धता के लिए अक्सर संसाधन प्रबंधन की आवश्यकता होती है"। एह? स्कोप केवल स्रोत कोड में मौजूद है और GC केवल रन-टाइम पर मौजूद है (और इसलिए, स्कोप के अस्तित्व के लिए पूरी तरह से अनजान है)।
जॉन हैरोप

@JonHarrop: मैं "स्कोप" शब्द का उपयोग उसी अर्थ में C ++ "स्कोप्ड पॉइंटर" के रूप में कर रहा था [वस्तु का जीवनकाल कंटेनर को पकड़े हुए होना चाहिए], क्योंकि यह मूल प्रश्न द्वारा निहित उपयोग है। मेरा कहना यह है कि वस्तुएं स्वयं के लिए संभावित रूप से लंबे समय तक रहने वाले संदर्भ बनाती हैं जैसे कि प्राप्त करने वाली घटनाएं विशुद्ध रूप से जीसी प्रणाली में स्वीकार्य नहीं हो सकती हैं। शुद्धता के लिए, कुछ संदर्भों को मजबूत होने की आवश्यकता है और कुछ संदर्भों को कमजोर होने की आवश्यकता है, और किन संदर्भों की आवश्यकता है जो इस बात पर निर्भर करेंगे कि किसी वस्तु का उपयोग कैसे किया जाता है। उदाहरण के लिए ...
सुपरकैट

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

@ सस्पर्कट: सही है। मैं यह नहीं कहूंगा कि ऐसा अक्सर होता है। मैं केवल 30 साल की प्रोग्रामिंग में एक बार भर में आया हूं।
जॉन हैरोप

7

क्लोज़र सभी आधुनिक भाषाओं के लिए बहुत आवश्यक हैं। वे जीसी के साथ लागू करने के लिए बहुत आसान हैं और आरएआई के साथ सही होने के लिए बहुत मुश्किल (हालांकि असंभव नहीं है), क्योंकि उनकी मुख्य विशेषताओं में से एक यह है कि वे आपको अपने चर के जीवनकाल में सार करने की अनुमति देते हैं!

C ++ उन्हें केवल 40 साल बाद मिला जब हर किसी ने किया, और इसे पाने के लिए बहुत सारे स्मार्ट लोगों ने बहुत मेहनत की। इसके विपरीत, प्रोग्रामिंग भाषाओं को डिजाइन और कार्यान्वित करने में शून्य ज्ञान वाले लोगों द्वारा डिजाइन और कार्यान्वित की जाने वाली कई स्क्रिप्टिंग भाषाएं उनके पास हैं।


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

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

2
@delnan: कैप्चर-बाय-रेफरेंस लैम्ब्डा के बहुत जानबूझकर उस [&]सिंटेक्स है। कोई भी C ++ प्रोग्रामर पहले ही &संकेत को संदर्भों के साथ जोड़ देता है और बासी संदर्भों के बारे में जानता है।
MSalters

2
@ ब्लॉकर्स आपकी बात क्या है? मैंने स्वयं संदर्भ कनेक्शन तैयार किया है। मैंने यह नहीं कहा कि सी ++ लैंबडास असाधारण रूप से असुरक्षित हैं, मैंने कहा कि वे संदर्भों के समान असुरक्षित हैं। मैंने यह तर्क नहीं दिया कि सी ++ लैंबडा खराब हैं, मैंने इस जवाब के दावे के खिलाफ तर्क दिया (कि सी ++ बहुत देर से बंद हुआ क्योंकि उन्हें यह पता लगाना था कि यह कैसे करना है)।

5
  1. SBMM कार्यक्रमों को अधिक निर्धारक बनाता है (आप किसी वस्तु के नष्ट होने पर ठीक-ठीक बता सकते हैं);

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

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

usingC # और useF # में देखें ।

  1. हीप मेमोरी भी (बहुत ही शान से, इमो) स्कोप-बाउंड हो सकती है (देखें सीडी :: सी में साझा + शेयर)।

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

SBMM का अधिक व्यापक रूप से उपयोग क्यों नहीं किया जाता है? इसके नुकसान क्या हैं?

SBMM सीमाएं जो आप कर सकते हैं:

  1. SBMM फर्स्ट-क्लास लेक्सिकल क्लोजर के साथ ऊपर की ओर फंगल समस्या पैदा करता है, यही वजह है कि क्लोजर C # जैसी भाषाओं में लोकप्रिय और प्रयोग करने में आसान है लेकिन C ++ में दुर्लभ और मुश्किल है। ध्यान दें कि प्रोग्रामिंग में कार्यात्मक निर्माणों के उपयोग के लिए एक सामान्य प्रवृत्ति है।

  2. SBMM को विध्वंसक की आवश्यकता होती है और वे किसी फ़ंक्शन को वापस करने से पहले अधिक कार्य जोड़कर टेल कॉल को बाधित करते हैं। टेल कॉल एक्सटेंसिबल स्टेट मशीनों के लिए उपयोगी होते हैं और .NET जैसी चीजों द्वारा प्रदान किए जाते हैं।

  3. कुछ डेटा संरचनाएं और एल्गोरिदम एसबीएमएम का उपयोग करके लागू करने के लिए कुख्यात हैं। मूल रूप से कहीं भी चक्र स्वाभाविक रूप से होते हैं। सबसे विशेष रूप से ग्राफ एल्गोरिदम। आप प्रभावी रूप से अपनी खुद की जीसी लिख रहे हैं।

  4. समवर्ती प्रोग्रामिंग कठिन है क्योंकि नियंत्रण प्रवाह और इसलिए, वस्तु जीवनकाल स्वाभाविक रूप से यहां गैर-नियतात्मक है। संदेश पासिंग सिस्टम में व्यावहारिक समाधान संदेशों की गहरी नकल और अत्यधिक लंबे जीवनकाल का उपयोग करते हैं।

  5. SBMM वस्तुओं को स्रोत कोड में उनके दायरे के अंत तक जीवित रखता है जो अक्सर आवश्यक से अधिक लंबा होता है और आवश्यकता से अधिक लंबा हो सकता है। इससे तैरने वाले कचरे की मात्रा बढ़ जाती है (अप्राप्य वस्तुओं का पुनर्नवीनीकरण होने का इंतजार)। इसके विपरीत, कचरा संग्रह ट्रेस वस्तुओं को जल्द ही मुक्त कर देता है क्योंकि अंतिम संदर्भ में वे गायब हो जाते हैं जो बहुत जल्द हो सकता है। मेमोरी प्रबंधन मिथकों को देखें : शीघ्रता

एसबीएमएम इतना सीमित है कि प्रोग्रामर को उन स्थितियों के लिए एक भागने के मार्ग की आवश्यकता होती है जहां जीवन के लिए घोंसला नहीं बनाया जा सकता है। C ++ में, shared_ptrभागने का मार्ग प्रदान करता है , लेकिन यह कचरा संग्रह का पता लगाने की तुलना में ~ 10x धीमा हो सकता है । इसलिए GC के बजाय SBMM का उपयोग करने से अधिकांश लोग ज्यादातर गलत तरीके से पैर रख देंगे। हालांकि, यह कहना नहीं है कि यह बेकार है। एसबीएमएम अभी भी सिस्टम और एम्बेडेड प्रोग्रामिंग के संदर्भ में मूल्य है जहां संसाधन सीमित हैं।

FWIW आप फोर्थ और एडा की जांच करना पसंद कर सकते हैं, और निकोलस विर्थ के काम पर पढ़ सकते हैं।


1
यदि आप कहते हैं कि कौन से बिट्स मैं लेखों को विस्तृत या उद्धृत करने में सक्षम हो सकता हूं।
जॉन हैरोप

2
सभी उपयोग के मामलों में सर्वव्यापी होने के विपरीत कुछ दुर्लभ उपयोग मामलों में 10x धीमा होना कितना प्रासंगिक है? C ++ में unique_ptr और अधिकांश प्रयोजनों के लिए पर्याप्त है। इसके बाद, RAII गर्त C ++ पर हमला करने के बजाय (एक ऐसी भाषा जो एक पुरातन भाषा होने के कारण नफरत करने के लिए बहुत प्यार करता है), यदि आप RAII गर्त पर हमला करने जा रहे हैं, तो आप RAII परिवार के एक छोटे भाई की कोशिश करें, उदाहरण के लिए जंग। मूल रूप से सब कुछ सही हो जाता है कि सी ++ गलत हो गया, जबकि ज्यादातर चीजें सही हो जाती हैं कि सी ++ सही हो गया। इसके अलावा 'का उपयोग करना' आपको उपयोग के मामलों का एक बहुत ही सीमित सेट मिलता है और रचना की उपेक्षा करता है।
user1703394

2
"सभी उपयोग के मामलों में सर्वव्यापी होने के विपरीत कुछ दुर्लभ उपयोग मामलों में 10x धीमा कैसे प्रासंगिक है?"। सबसे पहले, यह एक गोल तर्क है: shared_ptrकेवल C ++ में दुर्लभ है क्योंकि यह इतना धीमा है। दूसरे, यह एक सेब और संतरे की तुलना है (जैसा कि मैंने पहले ही बताए गए लेख में बताया है) क्योंकि shared_ptrउत्पादन जीसी की तुलना में कई गुना धीमा है। तीसरा, GCs सर्वव्यापी नहीं हैं और उन्हें LMax और रैपिड एडिशन के FIX इंजन जैसे सॉफ्टवेयर से बचा जाता है।
जॉन हैरोप

1
@ हारून, अगर आप कृपया मुझे बताएंगे। क्या जादू की रेसिपी आपने गहरी संसाधनों के उपयोग के सकर्मक प्रभावों को कम करने के लिए 30+ वर्ष गर्त का उपयोग किया है? 30+ वर्षों के बाद इस तरह के एक जादुई नुस्खा के बिना मैं केवल यह निष्कर्ष निकाल सकता हूं कि आपको अन्य कारणों से इसे काटे जाने का गलत मतलब होना चाहिए।
user1703394

1
@Jon Harrop, shared_ptr दुर्लभ नहीं है क्योंकि इसकी धीमी, इस कारण से दुर्लभ है कि शालीनता से डिजाइन की गई प्रणाली में 'साझा स्वामित्व' की आवश्यकता दुर्लभ है।
user1703394

4

TIOBE जैसे कुछ लोकप्रियता सूचकांक को देखते हुए (जो कि यकीनन सही है, लेकिन मुझे आपके इस तरह के प्रश्न का उपयोग करने के लिए इसका ठीक अनुमान है), आप सबसे पहले यह देखें कि शीर्ष 20 में से ~ 50% "भाषाएं" या "SQL बोलियाँ" हैं ", जहां" उपयोग में आसानी "और अमूर्तता के साधनों में नियतात्मक व्यवहार की तुलना में बहुत अधिक महत्व है। शेष "संकलित" भाषाओं से, लगभग 50% SBMM और ~ 50% भाषाओं के बिना हैं। इसलिए जब स्क्रिप्टिंग भाषाओं को आपकी गणना से बाहर निकालते हैं, तो मैं कहूंगा कि आपकी धारणा सिर्फ गलत है, संकलित भाषाओं में एसबीएमएम वाले बिना के रूप में लोकप्रिय हैं।


1
"उपयोग में आसानी" कैसे नियतत्ववाद से अलग है? क्या एक निर्धारक भाषा को एक गैर-निर्धारक की तुलना में उपयोग करने के लिए आसान नहीं माना जाना चाहिए?
फिलिप

2
@ फिलिप केवल उस चीज़ का है जो नियतात्मक है या वास्तव में मायने नहीं रखती है। ऑब्जेक्ट जीवन का समय अपने आप पर मायने नहीं रखता (हालांकि C ++ और दोस्त कई चीजें टाई करते हैं जो जीवन के समय को ऑब्जेक्ट करने के लिए मायने रखते हैं, क्योंकि वे कर सकते हैं)। जब एक पहुंच योग्य वस्तु को मुक्त कर दिया जाता है, तो कोई फर्क नहीं पड़ता क्योंकि, परिभाषा के अनुसार, आप इसका उपयोग नहीं कर रहे हैं।

एक और बात, विभिन्न "स्क्रिप्टिंग लैंग्वेज" जैसे पर्ल और पायथन भी मेमोरी मैनेजमेंट के लिए प्राथमिक गणना के रूप में संदर्भ गिनती का उपयोग करते हैं।
फिलिप

1
@Philipp कम से कम पायथन दुनिया में, इसे CPython का कार्यान्वयन विवरण माना जाता है, न कि भाषा की एक संपत्ति (और वास्तव में प्रत्येक अन्य कार्यान्वयन refcounting eschews)। इसके अलावा, मैं तर्क दूंगा कि बैकअप चक्र GC के साथ कैच-ऑल नो-ऑप्ट-आउट रेफरेंस काउंटिंग SBMM या RAII के रूप में योग्य नहीं है। वास्तव में, आपको RAII समर्थकों को खोजने के लिए कड़ी मेहनत की जाएगी जो कि RAII के लिए स्मृति प्रबंधन की इस शैली पर विचार कर रहे हैं (ज्यादातर ऐसा इसलिए है क्योंकि कहीं भी , साइकिल कहीं भी प्रोग्राम में कहीं और शीघ्र डीलडाउन को रोक नहीं सकती है)।

3

जीसी प्रणाली का एक बड़ा फायदा जो किसी ने अभी तक उल्लेख नहीं किया है वह यह है कि जब तक यह मौजूद है तब तक इसकी पहचान बनाए रखने के लिए एक जीसी प्रणाली में एक संदर्भ की गारंटी दी जाती है । यदि संदर्भ की प्रतियां मौजूद हैं, तो किसी ऑब्जेक्ट पर IDisposable.Dispose(.NET) या AutoCloseable.Close(जावा) कॉल करता है, तो वे प्रतियां उसी ऑब्जेक्ट को संदर्भित करती रहेंगी। ऑब्जेक्ट किसी भी चीज़ के लिए उपयोगी नहीं होगा, लेकिन इसका उपयोग करने के प्रयासों का ऑब्जेक्ट द्वारा नियंत्रित पूर्वानुमेय व्यवहार होगा। इसके विपरीत, C ++ में, यदि कोड deleteकिसी ऑब्जेक्ट पर कॉल करता है और बाद में इसका उपयोग करने की कोशिश करता है, तो सिस्टम की पूरी स्थिति पूरी तरह से अपरिभाषित हो जाती है।

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


4
पहली छमाही में आप जिस संपत्ति का उल्लेख करते हैं वह मेमोरी सुरक्षा है। जबकि एक जीसी मेमोरी सुरक्षा प्राप्त करने का एक बहुत आसान तरीका है, एक जीसी आवश्यक नहीं है: एक अच्छी तरह से किए गए उदाहरण के लिए जंग को देखें।

@delnan: जब मैं जंग- lang.org देखता हूं, तो मेरा ब्राउज़र वहां से उपयोगी तरीके से नेविगेट नहीं कर सकता है; मुझे और जानकारी कहाँ देखनी चाहिए? मेरी धारणा यह है कि GC के बिना मेमोरी सुरक्षा डेटा संरचनाओं पर कुछ प्रतिबंध लगाती है जो उन सभी चीजों के साथ अच्छी तरह से फिट नहीं हो सकते हैं जो एक आवेदन करने की आवश्यकता हो सकती है, लेकिन मुझे गलत साबित होने में खुशी होगी।
सुपरैट

1
मुझे इसके लिए अच्छे संदर्भों का एक भी (या यहां तक ​​कि छोटे सेट का) पता नहीं है; मेलिंग सूची (और विभिन्न ट्यूटोरियल, भाषा डिजाइन ब्लॉग पोस्ट, गितूब मुद्दे, ThisWeekInRust, और अधिक) सहित मेलिंग सूची (और मेल में जुड़े सभी सामानों को पढ़ने के लिए एक या दो साल से अधिक समय तक मेरा संचित ज्ञान जमा हुआ है। संक्षिप्त रूप से अपनी छाप को संबोधित करने के लिए: हाँ, प्रत्येक सुरक्षित निर्माण (आवश्यक रूप से) प्रतिबंध लगाता है, लेकिन वस्तुतः किसी भी मेमोरी सेफ कोड के लिए, एक उपयुक्त सुरक्षित निर्माण मौजूद है या लिखा जा सकता है। अब तक अधिकांश आम भाषा और stdlib में पहले से मौजूद हैं, अन्य सभी उपयोगकर्ता कोड में लिखे जा सकते हैं।

@ डायलेन: क्या रस्ट को संदर्भ काउंटरों में इंटरलॉक किए गए अपडेट की आवश्यकता होती है, या क्या इसके पास अपरिवर्तनीय वस्तुओं (या अपरिवर्तनीय रूप से लिपटे हुए म्यूटेबल ऑब्जेक्ट्स) से निपटने के कुछ अन्य साधन हैं, जिनका कोई निश्चित स्वामित्व नहीं है? क्या रस्ट में "ऑब्जेक्ट-ओनिंग" और "नॉन-ऑनिंग" दोनों बिंदुओं की अवधारणा है? मुझे "Xonor" पॉइंटर्स पर एक पेपर याद आता है, जिसमें उन वस्तुओं के विचार पर चर्चा की गई थी जो एक एकल संदर्भ है जो उन्हें "मालिक" करता है, और अन्य संदर्भ जो नहीं करते हैं; जब "मालिक" संदर्भ दायरे से बाहर हो जाता है, तो सभी गैर-मालिकाना संदर्भ मृत वस्तुओं के संदर्भ बन जाएंगे, और इस तरह की पहचान होगी ...
सुपरकैट

1
मुझे नहीं लगता कि एक भाषा के माध्यम से दौरे देने के लिए स्टैक एक्सचेंज टिप्पणियां सही माध्यम हैं। यदि आप अभी भी रुचि रखते हैं, तो आप सीधे स्रोत (# आईआरसी, जंग-देव मेलिंग सूची, आदि) पर जा सकते हैं और / या मुझे एक चैट रूम के साथ मार सकते हैं (आपको एक बनाने में सक्षम होना चाहिए)।

-2

सबसे पहले, यह महसूस करना बहुत महत्वपूर्ण है कि SIIM को RAII की बराबरी करना। या SBRM के लिए भी। RAII के सबसे आवश्यक (और कम से कम ज्ञात या सबसे अधिक प्रशंसित) गुणों में से एक यह तथ्य है कि यह 'एक संसाधन' होने के नाते एक संपत्ति है जो रचना के लिए सकर्मक नहीं है।

निम्न ब्लॉग पोस्ट RAII के इस महत्वपूर्ण पहलू पर चर्चा करता है और इसे गैर-निर्धारक जीसी का उपयोग करने वाली GCed भाषाओं में संसाधन संशोधन के विपरीत है।

http://minorfs.wordpress.com/2011/04/29/why-garbage-collection-is-anti-productive/

यह ध्यान रखना महत्वपूर्ण है कि जहां RAII का उपयोग C ++ में ज्यादातर किया जाता है, वहीं पायथन (पिछले गैर-वीएम आधारित संस्करण में) में विध्वंसक और निर्धारक जीसी होते हैं जो RAII को GC के साथ मिलकर उपयोग करने की अनुमति देते हैं। दोनों दुनिया के सर्वश्रेष्ठ अगर यह थे।


1
-1 यह मेरे द्वारा पढ़े गए सबसे बुरे लेखों में से एक है।
जॉन हैरोप

1
भाषाओं में समस्या यह नहीं है कि वे GC का समर्थन करते हैं, लेकिन वे RAII को छोड़ देते हैं। ऐसा कोई कारण नहीं है कि भाषा / रूपरेखा दोनों का समर्थन करने में सक्षम न हो।
सुपरकैट

1
@ जॉन हारोप, क्या आप विस्तृत कर सकते हैं। लेख में किए गए दावों में से, क्या पहले 3 दावों में से एक भी ऐसा है जो पकड़ में नहीं आता है? मुझे लगता है कि आप उत्पादकता के दावे पर असहमत हो सकते हैं, लेकिन अन्य 3 दावे बिल्कुल मान्य हैं। सबसे महत्वपूर्ण बात यह है कि संसाधन होने के रूप में परिवर्तनशीलता के बारे में पहला।
user1703394

2
@ user1703394: सबसे पहले, पूरा लेख एक स्ट्रोमैन "जीसीड भाषा" के आसपास आधारित है, जब वास्तव में, कचरा संग्रह के साथ इसका कोई लेना देना नहीं है। दूसरे, वह कचरा संग्रह को दोष देता है, जब वास्तव में, दोष ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग के साथ होते हैं। अंत में, उनके तर्क में 10 साल की देरी है। प्रोग्रामरों के विशाल बहुमत ने पहले से ही एकत्र की गई भाषाओं को सही ढंग से कचरा करने के लिए आधुनिकीकरण किया क्योंकि वे बहुत अधिक उत्पादकता प्रदान करते हैं।
जॉन हैरोप

1
उनके ठोस उदाहरण (रैम, ओपन फाइल हैंडल, लॉक, थ्रेड) काफी बता रहे हैं। मुझे याद है कि पिछली बार मुझे कोड लिखने के लिए दबाव डाला गया था, जिसमें से किसी से भी सीधे निपटना था। RAM के साथ, GC सब कुछ स्वचालित करता है। फाइल हैंडल के साथ मैं कोड लिखता हूं File.ReadLines file |> Seq.lengthजहां अमूर्त मेरे लिए समापन को संभालता है। ताले और धागे मैंने .NET Taskऔर F # से बदल दिए हैं MailboxProcessor। यह पूरा "हमने मैन्युअल संसाधन प्रबंधन की मात्रा में विस्फोट किया" केवल पूरी बकवास है।
जॉन हैरोप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.