2008-08-22 25 views
46

पाइथन ऑब्जेक्ट जीवनकाल को संभालने के लिए संदर्भ गणना विधि का उपयोग करता है। तो एक वस्तु जिसका अब और उपयोग नहीं है, तुरंत नष्ट हो जाएगा।जावा और पायथन कचरा संग्रहण विधियां अलग क्यों हैं?

लेकिन, जावा में, जीसी (कचरा कलेक्टर) उन वस्तुओं को नष्ट कर देता है जो अब किसी विशिष्ट समय पर उपयोग नहीं किए जाते हैं।

जावा इस रणनीति को क्यों चुनता है और इससे क्या फायदा होता है?

क्या यह पाइथन दृष्टिकोण से बेहतर है?

उत्तर

43

संदर्भ गणना का उपयोग करने में कमीएं हैं। सबसे उल्लिखित परिपत्र संदर्भों में से एक है: मान लें कि एक संदर्भ बी, बी संदर्भ सी और सी संदर्भ बी। यदि ए बी के संदर्भ को छोड़ना था, तो बी और सी दोनों में अभी भी 1 का संदर्भ गणना होगी और हटाया नहीं जाएगा पारंपरिक संदर्भ गिनती के साथ। सीपीथॉन (संदर्भ गिनती स्वयं पाइथन का हिस्सा नहीं है, लेकिन सी कार्यान्वयन का हिस्सा) एक अलग कचरा संग्रह दिनचर्या के साथ परिपत्र संदर्भों को पकड़ता है जो यह समय-समय पर चलता है ...

एक और दोष: संदर्भ गणना निष्पादन धीमा कर सकती है। प्रत्येक बार जब किसी ऑब्जेक्ट को संदर्भित किया जाता है और संदर्भित किया जाता है, तो दुभाषिया/वीएम को यह देखने के लिए जांच करनी चाहिए कि क्या गिनती 0 तक गिर गई है (और उसके बाद इसे रद्द कर दिया गया है)। कचरा संग्रह को ऐसा करने की आवश्यकता नहीं है।

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

+16

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

+1

दो अन्य कारणों के लिए संदर्भ गणना गिन/स्वीप जीसी से धीमी है: 1. संदर्भ गणनाओं को अद्यतन करने के लिए स्मृति लिखती है और समेकन की आवश्यकता होती है क्योंकि उन्हें सिंक्रनाइज़ेशन की आवश्यकता होती है। 2. संदर्भ गणना स्वयं अतिरिक्त स्मृति का उपयोग करती है, जो ऑब्जेक्ट आकार बढ़ाती है और इसलिए कैश दबाव में जोड़ती है। – mikera

13

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

उदाहरण के लिए, मैं CPython में लापरवाह, गैर पोर्टेबल कोड लिख सकते हैं इस तरह के

def parse_some_attrs(fname): 
    return open(fname).read().split("~~~")[2:4] 

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

तो तुम लिखने चाहिए कोड है कि लग रहा है

तरह
def parse_some_attrs(fname): 
    with open(fname) as f: 
     return f.read().split("~~~")[2:4] 

लेकिन कभी कभी लोगों को संदर्भ गिनती पर भरोसा करने की हमेशा अपने संसाधनों को मुक्त, क्योंकि यह कभी कभी अपने कोड में थोड़ा छोटा कर सकते हैं पसंद है।

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

+4

अच्छा जवाब। मेरे जवाब से एक प्रमुख बिंदु दूसरे उदाहरण में एक स्पष्ट 'बंद() 'का उपयोग नहीं है। पायथन में लिखने के लिए बहुत कम कोड। –

2

नवीनतम सूर्य जावा वीएम में वास्तव में कई जीसी एल्गोरिदम हैं जिन्हें आप ट्विक कर सकते हैं।जावा वीएम विनिर्देशों ने जानबूझकर अलग-अलग वीएम के लिए अलग-अलग (और एकाधिक) जीसी एल्गोरिदम की अनुमति देने के लिए वास्तविक जीसी व्यवहार को निर्दिष्ट किया है।

उदाहरण के लिए, डिफ़ॉल्ट सूर्य जावा वीएम जीसी व्यवहार के "स्टॉप-द-वर्ल्ड" दृष्टिकोण को नापसंद करने वाले सभी लोगों के लिए, IBM's WebSphere Real Time जैसे वीएम हैं जो रीयल-टाइम एप्लिकेशन को जावा पर चलाने की अनुमति देते हैं।

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

+0

("खुला के साथ" के लिए खोज) यह http://docs.python.org/howto/doanddont.html में समझाया गया है यह शायद आसान संदर्भ गिनती की अनुमति नहीं देता (यह मानते हुए आप provably गिनती किसी भी के तहत लीक नहीं संदर्भ के लिए सामान नहीं जोड़ सकते परिस्थिति)। मुझे यकीन नहीं है कि पाइथन इस से कैसे निपटता है, हालांकि मुझे लगता है कि कम से कम चक्र के लिए कुछ प्रकार की जांच है। –

2

संदर्भ गणना विशेष रूप से बहु-थ्रेडेड वातावरण में कुशलतापूर्वक करना मुश्किल है। मुझे नहीं पता कि हार्डवेयर हार्डवेयर लेनदेन या इसी तरह के (वर्तमान में) असामान्य परमाणु निर्देशों के बिना आप इसे कैसे करना शुरू कर देंगे।

संदर्भ गणना लागू करना आसान है। जेवीएम के पास प्रतिस्पर्धी कार्यान्वयन में बहुत पैसा है, इसलिए यह आश्चर्य की बात नहीं है कि वे बहुत मुश्किल समस्याओं के लिए बहुत अच्छे समाधान लागू करते हैं। हालांकि, यह JVM पर अपनी पसंदीदा भाषा को लक्षित करने में तेजी से आसान हो रहा है।

+0

सौभाग्य से यह वास्तव में, पायथन में एक मुद्दा है, खस्ताहाल सूत्रण समर्थन के साथ क्या हो प्रतीत नहीं होता है तो यह है कि जीआईएल के लिए अंत में एक सकारात्मक है ... – Basic

5

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

संदर्भ गिनती भी बहुत कुछ कचरा संग्रहण की तुलना में कुशल जगह नहीं है, क्योंकि यह स्मृति क्षण यह पहुँच योग्य नहीं हो जाता है reclaims [यह भी कारण है कि जी सी malloc की तुलना में तेजी हो सकता है/नि: शुल्क है]। यह तब अच्छा होता है जब आप ऑब्जेक्ट्स को फाइनलाइज़र संलग्न करना चाहते हैं (उदाहरण के लिए फ़ाइल ऑब्जेक्ट पहुंचने योग्य होने पर फ़ाइल को बंद करने के लिए)। एक संदर्भ गिनती प्रणाली तब भी काम कर सकती है जब स्मृति का केवल कुछ प्रतिशत मुक्त होता है। लेकिन प्रत्येक पॉइंटर असाइनमेंट पर बढ़ने और घटने वाले काउंटरों की प्रबंधन लागत में बहुत समय लगता है, और चक्रों को पुनः प्राप्त करने के लिए किसी प्रकार का कचरा संग्रह अभी भी आवश्यक है।

तो व्यापार-बंद स्पष्ट है: यदि आपको स्मृति-बाधित माहौल में काम करना है, या यदि आपको सटीक अंतिमकर्ता की आवश्यकता है, तो संदर्भ गणना का उपयोग करें। यदि आपके पास पर्याप्त स्मृति है और गति की आवश्यकता है, तो कचरा संग्रह का उपयोग करें।

26

असल में संदर्भ गणना और सूर्य जेवीएम द्वारा उपयोग की जाने वाली रणनीतियों कचरा संग्रहण एल्गोरिदम के सभी प्रकार हैं।

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

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

इसके अतिरिक्त जीसी के गिनती के संदर्भ में एक चक्र में किसी ऑब्जेक्ट को साफ करने के लिए एक चक्र डिटेक्टर की आवश्यकता होती है जो अकेले उनके संदर्भ गणना द्वारा पकड़ा नहीं जाएगा। पर्ल 5 में अपने जीसी कार्यान्वयन में एक चक्र डिटेक्टर नहीं था और चक्रीय स्मृति को रिसाव कर सकता था।

शोध यह भी दोनों दुनिया का सबसे अच्छा (कम ठहराव बार, उच्च प्रवाह क्षमता) प्राप्त करने के लिए किया गया है: http://cs.anu.edu.au/~Steve.Blackburn/pubs/papers/urc-oopsla-2003.pdf

1
देर खेल में

, लेकिन मुझे लगता है कि अजगर में आर सी के लिए एक महत्वपूर्ण तर्क अपनी सादगी है। उदाहरण के लिए, यह email by Alex Martelli देखें।

(मैं अजगर सूची पर 13 वीं अक्टूबर 2005 से गूगल कैश से बाहर लिंक, ईमेल की तारीख नहीं मिल सकता है)। जावा के अनुरेखण जीसी की

+1

(जब तक आप Jython/IPython/आदि ऑप्टिकल फाइबर केबल पर हैं) मैं इस बारे में सोच गलत लिंक है। – mtasic85

3

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

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

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

+0

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

+0

http://patshaughnessy.net/2013/10/24/visualizing-garbage-collection-in-ruby-and-python – codefire

+0

@codefire कुछ ट्रेसिंग जीसी कार्यान्वयन दुनिया को रोकने का कारण नहीं बनेंगे। Azul Zing JVM ने इसे कार्यान्वित किया है। यहां एल्गोरिदम है, http://www.azulsystems.com/sites/default/files/images/c4_paper_acm.pdf –

संबंधित मुद्दे