नया स्वचालित संदर्भ गिनती तंत्र कैसे काम करता है?


206

क्या कोई मुझे संक्षेप में बता सकता है कि ARC कैसे काम करता है? मुझे पता है कि यह कचरा संग्रह से अलग है, लेकिन मैं बस सोच रहा था कि यह कैसे काम करता है।

इसके अलावा, अगर ARC वह करता है जो GC बिना प्रदर्शन में बाधा डाले करता है, तो Java GC का उपयोग क्यों करता है? यह एआरसी का उपयोग क्यों नहीं करता है?


2
यह आपको इसके बारे में सब कुछ बताएगा: http://clang.llvm.org/docs/AutomaticReferenceCounting.html Xcode और iOS 5 में इसे कैसे लागू किया गया है यह NDA के अंतर्गत है।
मोर्टन फास्ट

14
@ मम्बेन यह खराब सलाह है। मैं लॉग इन नहीं करना चाहता या यहां तक ​​कि आईओएस देव केंद्र के लिए भी खाता है, लेकिन मैं एआरसी के बारे में जानने में दिलचस्पी रखता हूं।
एंड्रेस एफ।

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

@TaylanUB: "अधिक मेमोरी की आवश्यकता है"। बहुत सारे लोग कहते हैं कि लेकिन मुझे विश्वास करना मुश्किल है।
जॉन हैरोप

2
@JonHarrop: वर्तमान में मुझे यह भी याद नहीं है कि मैंने ऐसा क्यों कहा था, ईमानदार होना। :-) इस बीच मुझे एहसास हुआ कि जीसी की कई अलग-अलग रणनीतियाँ हैं, ऐसे कंबल बयान शायद सभी बेकार हैं। मुझे हंस बोहेम को उनके स्मृति आवंटन मिथकों और अर्ध-सत्य से अवगत कराएं : "यह क्षेत्र संदिग्ध लोक-ज्ञानियों से इतना प्रभावित क्यों है?"
तैलानुब

जवाबों:


244

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

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

स्वचालित संदर्भ गणना (ARC) अगला तार्किक कदम है। यदि कंपाइलर यह पहचान सकता है कि आपको वस्तुओं को कहाँ रखना और जारी करना चाहिए, तो आपके लिए यह कोड क्यों नहीं है? कठोर, दोहराए जाने वाले कार्य वे कौन से संकलक हैं और उनके भाइयों में महान हैं। मनुष्य चीजों को भूल जाता है और गलतियाँ करता है, लेकिन कंप्यूटर बहुत अधिक सुसंगत हैं।

हालाँकि, यह आपको इन प्लेटफार्मों पर स्मृति प्रबंधन की चिंता से पूरी तरह मुक्त नहीं करता है। मैं यहाँ अपने उत्तर में (चक्र को बनाए रखने के लिए) देखने के लिए प्राथमिक मुद्दे का वर्णन करता हूं , जिसके लिए कमजोर मतदाताओं को चिह्नित करने के लिए आपके हिस्से पर थोड़ा विचार करना पड़ सकता है। हालाँकि, यह मामूली है जब आप एआरसी में हासिल कर रहे हैं की तुलना में।

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

जैसे कि क्या इसे अन्य भाषाओं में बढ़ाया जा सकता है, यह ऑब्जेक्टिव-सी में रेफरेंस काउंटिंग सिस्टम के आस-पास लगता है। इसे जावा या अन्य भाषाओं में लागू करना मुश्किल हो सकता है, लेकिन मुझे एक निश्चित विवरण बनाने के लिए निम्न-स्तरीय संकलक विवरण के बारे में पर्याप्त नहीं पता है। यह देखते हुए कि Apple LLVM में इस प्रयास को आगे बढ़ा रहा है, ऑब्जेक्टिव-सी पहली बार आएगा, जब तक कि कोई अन्य पार्टी अपने स्वयं के महत्वपूर्ण संसाधनों को लागू न करे।

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


56
जोर मेरा: यह आपको पूरी तरह से स्मृति प्रबंधन के बारे में चिंता करने से मुक्त नहीं करता है
बिशर्ले

6
क्या ARC वास्तव में एक नवीनता है? आपके उत्तर से मैं यह निष्कर्ष निकालता हूं कि एआरसी एक नई अवधारणा है, जिसका उपयोग पहली बार ऑब्जेक्टिव-सी में किया गया है (सही होने पर मुझे सही करें)। सच कहूं तो, मैं एक ऑब्जेक्टिव-सी डेवलपर नहीं हूं और एआरसी के बारे में ज्यादा नहीं जानता, लेकिन क्या बूस्ट शेयर्ड पॉइंटर्स (बूस्ट। देखें) बिल्कुल एक ही चीज नहीं हैं? और अगर वे नहीं हैं, तो क्या अंतर है?
दीमी

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

6
"यह नया है" सवाल का जवाब देने के लिए, डेल्फी ने एक दशक से भी अधिक समय तक स्ट्रिंग्स, सरणियों और इंटरफेस (COM समर्थन के लिए) के लिए स्वचालित संदर्भ गिनती की है। मैं मानता हूं कि यह वास्तव में एक gc'd पर्यावरण और "यह सब मैन्युअल रूप से करते हैं" पर्यावरण के बीच एक अच्छा समझौता है। मुझे खुशी है कि यह ObjC और LLVM में है (इसलिए अन्य भाषाएं भी इसका लाभ उठा सकती हैं)।
20

2
@theDmi: "क्या ARC वास्तव में एक नवीनता है?"। ऑटोमैटिक रेफरेंस काउंटिंग की खोज 1960 में की गई थी और इसका इस्तेमाल कई भाषाओं जैसे पायथन और मैथमेटिका में किया गया है। जेवीएम या सीएलआर में इसका उपयोग नहीं किया जाता है क्योंकि यह बहुत धीमा है और चक्रों को लीक करता है।
जॉन हैरोप

25

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

दूसरी ओर एआरसी (या एमआरसी) के साथ कुछ प्रकार की डेटा संरचना संभव नहीं है, जबकि जीसी उन्हें संभाल सकते हैं।

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

पसंद:

A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A

ए का उपयोग करते समय सब ठीक है (स्थानीय चर के माध्यम से कहें)।

जब आप इसे (और बी 1 / बी 2 / बी 3) के साथ किया जाता है, तो एक जीसी प्रणाली अंततः सब कुछ को देखने का फैसला करेगी जो स्टैक और सीपीयू रजिस्टरों से शुरू हो सकती है। यह ए, बी 1, बी 2, बी 3 कभी नहीं मिलेगा, इसलिए यह उन्हें अंतिम रूप देगा और अन्य वस्तुओं में मेमोरी को रीसायकल करेगा।

जब आप एआरसी या एमआरसी का उपयोग करते हैं, और ए के साथ खत्म होता है, तो इसमें 3 (बी 1, बी 2, और बी 3 का एक संदर्भ होता है), और बी 1 / बी 2 / बी 3 में सभी संदर्भ संख्या 1 (ए का एनएसएरे) एक संदर्भ रखती है। से प्रत्येक)। इसलिए वे सभी वस्तुएं जीवित रहती हैं, हालांकि कुछ भी कभी भी उनका उपयोग नहीं कर सकता है।

आम समाधान यह है कि उन संदर्भों में से एक को कमजोर करने की आवश्यकता है (संदर्भ गणना में योगदान नहीं)। यह कुछ उपयोग पैटर्न के लिए काम करेगा, उदाहरण के लिए यदि आप B1 / B2 / B3 को केवल A के माध्यम से संदर्भित करते हैं, हालांकि अन्य पैटर्न में यह विफल रहता है। उदाहरण के लिए यदि आप कभी-कभी बी 1 पर पकड़ लेंगे, और माता-पिता सूचक के माध्यम से वापस ऊपर चढ़ने की उम्मीद करेंगे और ए को पाएंगे कमजोर संदर्भ के साथ यदि आप केवल बी 1 पर पकड़ते हैं, तो ए (और सामान्य रूप से) वाष्पित हो जाएगा, और बी 2 और बी 3 ले सकते हैं। इसके साथ।

कभी-कभी यह कोई समस्या नहीं है, लेकिन डेटा की जटिल संरचनाओं के साथ काम करने के कुछ बहुत ही उपयोगी और प्राकृतिक तरीके एआरसी / एमआरसी के साथ उपयोग करना बहुत मुश्किल है।

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

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


"दूसरी ओर एआरसी के साथ कुछ प्रकार की डेटा संरचना संभव नहीं है" मुझे लगता है कि आपका मतलब था कि बिना संकेत के स्वचालित सफाई संभव नहीं है; जाहिर है, डेटा संरचनाएं हैं।
स्टीवन फिशर

निश्चित रूप से, लेकिन ओआरजीसी ऑब्जेक्ट्स का केवल स्वचालित सफाई एआरसी के तहत उपलब्ध है, इसलिए "कोई स्वचालित सफाई नहीं" == "कोई सफाई नहीं"। मैं तब जवाब दूंगा जब मेरे पास अधिक समय होगा।
स्ट्रिप्स

@ स्ट्राइप्स: एआरसी में मैनुअल क्लीनअप के बराबर साइकल का मैन्युअल ब्रेकिंग है, जैसे foo = nil
डगलस

"[एआरसी] में उच्च प्रदर्शन होगा ... एआरसी प्रदर्शन पर एक बड़ी प्राथमिकता देता है"। मुझे यह पढ़कर हैरानी हुई कि जब यह अच्छी तरह से पता है कि कचरा संग्रह को ट्रेस करने की तुलना में संदर्भ गिनती बहुत धीमी है। फ्लाइंगफ्रॉगब्लॉग .blogspot.co.uk
जॉन

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

4

जादू

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

कुछ अन्य सुधारों में कमजोर संदर्भों को शून्य करना, ब्लॉक के ढेर को स्वचालित रूप से कॉपी करना, बोर्ड भर में स्पीडअप (ऑटोरेलिज पूल के लिए 6x) शामिल हैं।

एआरसी पर एलएलवीएम डॉक्स में यह सब कैसे काम करता है, इस बारे में अधिक विस्तृत चर्चा ।


2
-1 "एआरसी एक संकलित समय तकनीक है, जीसी के विपरीत जो रनटाइम है और आपके प्रदर्शन को नकारात्मक रूप से प्रभावित करेगा"। संदर्भ गणना रन-टाइम पर टकरा जाती है जो बहुत अक्षम है। यही कारण है कि JVM और .NET जैसे GCs का पता लगाना बहुत तेज़ है।
जॉन हैरोप

1
@ जॉन: क्या आपके पास इसका कोई सबूत है? मेरे अपने पढ़ने से, ऐसा लगता है कि नए RC एल्गोरिदम आमतौर पर M & S GC से बेहतर या बेहतर प्रदर्शन करते हैं।
xryl669

1
@ xryl669: जीसी हैंडबुक ( gchandbook.org ) में पूरी व्याख्या है । ध्यान दें कि अनुरेखण! = M & S।
जॉन हैरोप

3

यह कचरा संग्रहण से बहुत भिन्न होता है। क्या आपने चेतावनी देखी है जो आपको बताती है कि आप विभिन्न रेखाओं पर वस्तुओं को लीक कर सकते हैं? वे कथन यहां तक ​​कि आपको यह भी बताते हैं कि आपने किस लाइन को ऑब्जेक्ट आवंटित किया है। यह एक कदम आगे ले जाया गया है और अब लगभग 100% समय में, अधिकांश प्रोग्रामर की तुलना में, उचित स्थानों पर retain/ releaseबयान डाल सकते हैं । कभी-कभी कुछ बनाए गए ऑब्जेक्ट्स के कुछ अजीब उदाहरण हैं जिन्हें आपको इसके साथ मदद करने की आवश्यकता है।


0

Apple डेवलपर प्रलेखन द्वारा बहुत अच्छी तरह से समझाया गया है। पढ़ें "कैसे एआरसी वर्क्स"

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

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

डिफ को जानने के लिए। कचरा संग्रहण और एआरसी के बीच: पढ़ें इस


0

एआरसी एक संकलक सुविधा है जो वस्तुओं का स्वचालित मेमोरी प्रबंधन प्रदान करती है।

इसके बजाय आपको याद रखना है कि कब उपयोग करना है retain, release, और autorelease, एआरसी आपकी वस्तुओं के जीवनकाल की आवश्यकताओं का मूल्यांकन करता है और संकलन समय पर स्वचालित रूप से आपके लिए उपयुक्त मेमोरी प्रबंधन कॉल सम्मिलित करता है। संकलक भी आपके लिए उपयुक्त डीलॉक तरीके उत्पन्न करता है।

कंपाइलर retain/releaseसमय पर आवश्यक कॉल्स सम्मिलित करता है , लेकिन उन कॉल्स को रनटाइम पर निष्पादित किया जाता है, किसी अन्य कोड की तरह।

निम्नलिखित आरेख आपको बेहतर समझ देगा कि एआरसी कैसे काम करता है।

यहां छवि विवरण दर्ज करें

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

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