بالمقارنة مع C ++ ، يبدو جامع القمامة Cمثل السحر ، ويمكنك بسهولة كتابة التعليمات البرمجية دون القلق بشأن الذاكرة الأساسية. ولكن إذا كنت تهتم بالأداء ، فإن معرفة كيفية إدارة وقت تشغيل. NET لذاكرة الوصول العشوائي الخاصة به يمكن أن يساعدك في كتابة تعليمات برمجية أفضل.
أنواع القيم مقابل أنواع المراجع
هناك نوعان من الأنواع في. NET ، والتي تؤثر بشكل مباشر على كيفية التعامل مع الذاكرة الأساسية.
أنواع القيمة هي أنواع بدائية ذات أحجام ثابتة مثل
int
،
bool
، float
،
double
، إلخ. يتم تمريرها بالقيمة ، مما يعني أنه إذا اتصلت بـ
someFunction (int arg)
، يتم نسخ الحجة وإرسالها كموقع جديد في الذاكرة.
تحت الغطاء ، يتم (عادة) تخزين أنواع القيم في المكدس. ينطبق هذا في الغالب على المتغيرات المحلية ، وهناك الكثير من الاستثناءات حيث سيتم تخزينها بدلاً من ذلك على الكومة. لكن في جميع الحالات ، الموقع في الذاكرة حيث يوجد نوع القيمة يحمل القيمة الفعلية لهذا المتغير.
المكدس هو مجرد موقع خاص في الذاكرة ، تمت تهيئته بقيمة افتراضية ولكنه قادر على التوسع. المكدس هو بنية بيانات Last-in ، First-out (LIFO). يمكنك التفكير في الأمر مثل إضافة متغيرات الجرافة إلى الجزء العلوي من الحاوية ، وعندما تخرج عن النطاق ، تصل. NET إلى الحاوية وتزيلها واحدة تلو الأخرى حتى تصل إلى القاع.

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

هذا أيضًا هو المكان الذي يأتي منه مصطلح "StackOverflow" ، والذي ينتج عندما تحتوي الوظيفة على عدد كبير جدًا من استدعاءات الطريقة المتداخلة وتملأ المكدس بأكمله.
أنواع المراجعمع ذلك ، إما أنها كبيرة جدًا أو ليس لها أحجام ثابتة أو تعيش لفترة طويلة جدًا بحيث لا يمكن وضعها في المكدس. عادة ، تأخذ هذه شكل كائنات وفئات تم إنشاء مثيل لها ، ولكنها تتضمن أيضًا مصفوفات وسلاسل ، والتي يمكن أن تختلف في الحجم.
غالبًا ما تتم تهيئة أنواع المراجع مثل مثيلات الفئات باستخدام الكلمة الرئيسية
new، مما يؤدي إلى إنشاء مثيل جديد للفئة وإرجاع مرجع إليها. يمكنك تعيين هذا إلى متغير محلي ، والذي يستخدم بالفعل المكدس لتخزين المرجع إلى الموقع على الكومة.
يمكن أن تتوسع الكومة وتملأ حتى نفاد ذاكرة الكمبيوتر ، مما يجعلها رائعة لتخزين الكثير من البيانات. ومع ذلك ، فهي غير منظمة ، وفي Cيجب إدارتها باستخدام أداة تجميع البيانات المهملة لتعمل بشكل صحيح. تكون عمليات تخصيص الكومة أيضًا أبطأ من عمليات تخصيص المكدس ، على الرغم من أنها لا تزال سريعة جدًا.

ومع ذلك ، هناك عدد من الاستثناءات لهذه القواعد ، وإلا فسيتم تسمية أنواع القيمة والمراجع "أنواع المكدس" و "أنواع الكومة".
- المتغيرات الخارجية لوظائف lambda والمتغيرات المحلية لـ
IEnumerator
block والمتغيرات المحلية لطرقasyncكلها مخزنة في الكومة.
- حقول نوع القيمة للفئات هي متغيرات طويلة المدى ، ويتم تخزينها دائمًا في الكومة. يتم تغليفها أيضًا بنوع مرجعي ، ويتم تخزينها جنبًا إلى جنب مع نوع المرجع هذا.
- يتم أيضًا تخزين حقول الفئة الثابتة دائمًا في الكومة.
- البنيات المخصصة هي أنواع قيم ، لكن يمكن أن تحتوي على أنواع مرجعية مثل القوائم والسلاسل ، والتي يتم تخزينها في الكومة كالمعتاد. يؤدي إنشاء نسخة من البنية إلى إنشاء نسخة جديدة وتخصيص جميع أنواع المراجع على الكومة.
الاستثناء الأكثر بروزًا لقاعدة "أنواع المراجع موجودة في الكومة" ، هو استخدام
stackalloc
مع
Span، الذي يخصص يدويًا كتلة من الذاكرة على المكدس لصفيف مؤقت سيتم تنظيفه من المكدس كالمعتاد عندما يخرج عن النطاق. هذا يتجاوز تخصيص كومة مكلف نسبيًا ، ويضع ضغطًا أقل على جامع القمامة في هذه العملية. يمكن أن تكون أكثر فاعلية ، لكنها ميزة متقدمة بعض الشيء ، لذلك إذا كنت ترغب في معرفة المزيد عنها ، يمكنك قراءة هذا الدليل حول كيفية استخدامها بشكل صحيح دون التسبب في استثناء StackOverflow.
ما هو جمع القمامة؟
المكدس منظم للغاية ، لكن الكومة فوضوية. بدون وجود شيء لإدارته ، لا يتم تنظيف الأشياء الموجودة على الكومة تلقائيًا ، مما يؤدي إلى نفاد ذاكرة التطبيق بسبب عدم تحريره مطلقًا.
بالطبع ، هذه مشكلة ، وهذا هو سبب وجود أداة جمع القمامة. يتم تشغيله على مؤشر ترابط في الخلفية ويقوم بشكل دوري بمسح تطبيقك بحثًا عن مراجع لم تعد موجودة في المكدس ، مما يشير إلى أن البرنامج قد توقف عن الاهتمام بالبيانات التي يتم الرجوع إليها. يمكن أن يأتي وقت تشغيل. NET وتنظيفه ، وتحويل الذاكرة في هذه العملية لجعل الكومة أكثر تنظيماً.

ومع ذلك ، يأتي هذا السحر بتكلفة جمع القمامة بطيئة ومكلفة.يتم تشغيله على مؤشر ترابط في الخلفية ، ولكن هناك فترة يجب فيها إيقاف تنفيذ البرنامج لتشغيل مجموعة البيانات المهملة. هذه هي المقايضة التي تأتي مع البرمجة في C؛ كل ما يمكنك فعله هو محاولة تقليل القمامة التي تصنعها
في اللغات التي لا تحتوي على جامع للقمامة ، تحتاج إلى التنظيف يدويًا بنفسك ، وهو أسرع في كثير من الحالات ولكنه أكثر إزعاجًا للمبرمج. لذا ، بمعنى ما ، جامع القمامة يشبه جهاز Roomba ، الذي ينظف أرضياتك تلقائيًا ، ولكنه أبطأ من مجرد الاستيقاظ والكنس.