[Objective-c] كيف تعمل آلية احتساب المراجع الأوتوماتيكية الجديدة؟


Answers

ARC هو مجرد لعب القديم / الإفراج (MRC) مع المجمع من معرفة متى استدعاء الاحتفاظ / الإصدار. ستميل إلى الحصول على أداء أعلى ، واستخدام أقل للذاكرة ، وأداء أكثر قابلية للتنبؤ من نظام GC.

من ناحية أخرى ، بعض أنواع بنية البيانات غير ممكنة مع ARC (أو MRC) ، بينما GC يمكن التعامل معها.

على سبيل المثال ، إذا كان لديك فئة مسماة عقدة ، وعقدة لديها NSArray من الأطفال ، ومرجع واحد إلى والدته "يعمل فقط" مع GC. مع ARC (والعد مرجع اليدوي كذلك) لديك مشكلة. سيتم الإشارة إلى أي عقدة محددة من أطفالها وكذلك من أصلها.

مثل:

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

كل شيء على ما يرام بينما كنت تستخدم A (قل عن طريق متغير محلي).

عندما تنتهي من ذلك (و B1 / B2 / B3) ، سيقرر نظام GC في نهاية الأمر النظر في كل شيء يمكن أن تجده بداية من مكدس الذاكرة المؤقتة وسجلات وحدة المعالجة المركزية. لن تجد أبداً A ، B1 ، B2 ، B3 حتى تقوم بوضع اللمسات الأخيرة عليها وإعادة تدوير الذاكرة إلى كائنات أخرى.

عندما تستخدم ARC أو MRC ، وتنتهي بـ A ، يكون لها مبلغ 3 (B1 و B2 و B3) ، و B1 / B2 / B3 سيحتوي كل منها على عدد مرجعي واحد (A NSArray يحمل إشارة واحدة إلى كل). لذلك تبقى كل تلك الكائنات حية حتى ولو لا شيء يمكن استخدامها من أي وقت مضى.

الحل المشترك هو أن تقرر أن أحد هذه المراجع يجب أن يكون ضعيفًا (لا يساهم في حساب المرجع). سيعمل ذلك على بعض أنماط الاستخدام ، على سبيل المثال ، إذا كنت تشير إلى B1 / B2 / B3 فقط عبر A. ومع ذلك في الأنماط الأخرى ، فإنه يفشل. على سبيل المثال ، إذا كنت ستحتفظ بـ B1 في بعض الأحيان ، ونتوقع الصعود مرة أخرى عبر المؤشر الرئيسي والعثور على A. مع مرجع ضعيف إذا قمت بالاحتفاظ بـ B1 فقط ، فستتلاشى A (ويمكن أن تتلاشى عادة) ، وتتخذ B2 ، و B3 مع ذلك.

في بعض الأحيان ، هذه ليست مشكلة ، ولكن من الصعب جدًا استخدام طرق ARC / MRC مع الطرق المفيدة والطبيعية جدًا للتعامل مع هياكل معقدة من البيانات.

لذلك تستهدف ARC نفس النوع من المشاكل أهداف GC. ومع ذلك ، ARC يعمل على مجموعة محدودة من أنماط الاستخدام ثم GC ، لذلك إذا أخذت لغة GC (مثل Java) وطعمت شيئا مثل ARC عليه ، لن تعمل بعض البرامج أكثر (أو على الأقل ستولد أطنان من الذاكرة المهجورة ، وقد تتسبب في مشاكل مبادلة خطيرة أو نفاد الذاكرة أو مساحة المبادلة).

يمكنك أيضًا أن تقول أن ARC تضع أولوية أكبر على الأداء (أو ربما القدرة على التنبؤ) بينما يضع GC أولوية أكبر على كونه حلًا عامًا. ونتيجة لذلك ، فإن GC لديها متطلبات ذاكرة / ذاكرة أقل قابلية للتنبؤ ، وأداء أقل (عادة) من ARC ، ولكن يمكنها التعامل مع أي نمط استخدام. سوف يعمل ARC بشكل أفضل بكثير للعديد من أنماط الاستخدام الشائعة ، ولكن بالنسبة لأنماط الاستخدام القليلة (الصالحة!) ، فسوف يتلاشى ويموت.

Question

هل يمكن لأي أحد أن يوضح لي كيف تعمل ARC؟ أعلم أنه مختلف عن مجموعة القمامة ، لكنني كنت أتساءل فقط كيف نجحت.

أيضا ، إذا ARC يفعل ما يفعل GC دون عرقلة الأداء ، فلماذا تستخدم Java GC؟ لماذا لا يستخدم ARC كذلك؟




يختلف بشكل كبير من جمع القمامة. هل شاهدت التحذيرات التي تخبرك أنك قد تسرّب أشياء على خطوط مختلفة؟ حتى تلك العبارات تخبرك على أي خط قمت بتخصيص الكائن. وقد اتخذ هذا خطوة أبعد ويمكن الآن إدراج بيانات retain / release في المواقع المناسبة ، أفضل من معظم المبرمجين ، ما يقرب من 100 ٪ من الوقت. من حين لآخر توجد بعض الحالات الغريبة للأشياء المحتفظ بها والتي تحتاج إلى مساعدتها.