khaled_prg

الــ GC بين حرية الماضي و قيود الحاضر !

3 ردود في هذا الموضوع

السلام عليكم

مقدمة : (على طريقة "فيصل القاسم" :D)

هل أصبحت ظاهرة المؤشرات أو ما بات يُعرف بــ "عفاريت البرمجة" ظاهرة برمجية محلية ! تستهدف أبناء العم Dennis Ritchie لتهدد أمن برامجهم و تخيفهم أكثر ؟

أم أنها إشاعات مُغرضة ! هدفها الإضرار بسمعة المؤشرات في أوساط المبرمجين ؟

ثم .. لماذا كل هذا التهويل ؟؟

أليس من المنطقي استخدام المؤشرات للوصول إلى الهدف بسرعة أكبر ؟

أليس من شأنها تحسين سرعة و أداء تنفيذ البرنامج ؟

.. ألا يعود لها الفضل في تمييز لغتى السي و السي++ دون غيرهن من اللغات ؟

أم أن تعقيد المؤشرات طغى على سرعتها ؟ رغم عدم وجود بديل, يتساءل البعض !

و لكن في المقابل, و كما يقول المثل : أهل مكة أدرى بشعابها ..

أليس حريا بمبرمجي السي++ أن يكونوا على علم بخبايا و خفايا المؤشرات و إدارة شؤون الذاكرة ؟

أم أن صعوبة المؤشرات تقف عائقا دون هذا الأمر ؟

أسئلة من بين أخرى نُحاول أن نُجيب عليها في هذا الموضوع.

فاصل و نواصل .. :happy:

_______________________________

عُدنا :cool:

ماهو الــ GC و مالحاجة إليه ؟

الإعلان عن مؤشر و عدم تحريره عند الإنتهاء من استخدامه, أمرٌ قد لا يُلفت انتباه معظم المبرمجين الذين لم يعتادوا بعد على التعامل مع المؤشرات.

خطورة التعامل مع المؤشرات و إدارة الذاكرو يدوياً دفعت بمايكروسوفت إلى انتاج طقم الدوت نت حيث أدخلت Microsoft "جامع مخلفات" خاص لمنصة الــ .NET و يتم تفعيله في C++ بشكل اختياري على عكس C# مثلا.

يتم تنظيف الذاكرة باستخدام برنامج يُسمى Garbage Collector أو "ململم النفايات" أو "جامع المخلفات", يقوم الـــ GC بتحديد الأجزاء من البرامج التي لن يتم استخدامها في المستقبل ثم يقوم باستعادة الموارد التي كانت تستخدمها هذه الأجزاء (المساحة التخزينية وغيرها).

لا ننسى أن الاختراع الأول للـــ Garbage collection تم من طرف العالم الأميريكي John McCarthy عام 1959 من أجل حل مشاكل تنظيم الذاكرة اليدوي (manual memory management) التي كان يواجهها أثناء استخدام لغة LISP.

للعلم, حصل جون عام 1971 على جائزة تيورنج لمساهماته الكبيرة في علم الذكاء الاصطناعي حيث يعود له الفضل في اختيار لفظ الذكاء الاصطناعي وإطلاقه على هذا العلم.

إيجابيات و سلبياته

لنستعرض معاً و بشكل سريع سلبيات و إيجابيات الــ GC.

إيجابياته :

  • لا تُهمنا فترة حياة الكائن, لأنه سيتم تحريره من الذاكرة حالما يتم الإنتهاء من استخدامه.
  • يُمكننا توزيع الــ Object على عدة كائنات أخرى دون أن نُفكر في كيفية تحرير مساحة الذاكرة التي يحجزها هذا الأخير و بالتالي يُمكننا استخدام الــ Immutable Patterns و الاقتصاد في إنشاء العديد من الكائنات.
  • يقوم الــ GC بالحجز و التحرير عن طريق القيام بالــ processing blocks و بالتالي إذا تم إنشاء/هدم 1000 كائن فإن الــ GC سيحجز و يحرر بضع مرات فقط, في هذه الحالة سيكون الأمر أفضل بكثير من حجز و تحرير الذاكرة بشكل يدوي.
  • مثلا, لو أردنا تنفيذ الكود التالي :
    for (int i=0; i<1000; i++) {
    Object temp = new Object[1024];
    }


    إذا تم الحجز بصفة يدوية سنحصل على 1000 عملية حجز/تحرير أما في الــ GC فسيتم تجميع عمليات الحجز و بالتالي ستكون التكلفة أقل .. لو قمنا بتنفيذ الكود السابق باستخدام الخيار -verbose:gc الذي يُظهر عمليات الحجز التي يقوم بها الــ GC ستكون النتيجة :

    [GC 892K->105K(5056K), 0.0016256 secs]
    [GC 998K->105K(5056K), 0.0005996 secs]
    [GC 999K->105K(5056K), 0.0002923 secs]
    [GC 1001K->105K(5056K), 0.0001104 secs]


  • الــ GC لا يمنع تحرير الكائنات بشكل يدوي, في الجافا مثلا يمكن أن نكتب نقوم بتحرير كائن هكذا :
    Object o = new Object();
    ...
    o = null-gc;


  • تسيير الكائنات المحجوزة من طرف الــ GC يكون سريعاً جداً لأن الحجز يتم على مستوى الــ memory blocks.

سلبياته :

  • يُصيب المبرمج بمرض "الزهايمر" حيث ينسى تماما معنى "تحرير الذاكرة" !
  • في لحظة معينة, يحجز الــ GC مساحة من الذاكرة (قد تكون أكثر من ما يحتاجه) من أجل ضبط و تسيير عمليات الحجز القادمة, فمثلا عند تشغيل البرنامج يقوم الــ GC بحجز مساحة 2 Mo من الذاكرة. (القيمة الإفتراضية)
  • يحجز الـــ GC من الـــ Heap (القيمة الإفتراضية هي 2 Mo و القيمة القصوى هي 64 Mo) إذا كان التطبيق يحتاج إلى أكثر من المساحة القصوى سنحصل على Exception حتى لو كان النظام يملك مساحة متبقية, لحل هذه المشكلة يجب تخصيص الحجم الأقصى قبل تنفيذ البرنامج أو يمكن استخدام الـــ RFE في الجافا.
  • لا يُمكننا معرفة الوقت الحقيقي الذي تمت فيه عملية التحرير (بغض النظر عن وجود حلول جزئية مثل الــ PhantomReference في الجافا)
  • يتسبب في عمليات تنظيف دورية للذاكرة مما يتسبب في بطء البرنامج.
  • يُستحسن دائما القيام بضبط إعدادات الــ GC حسب الحاجة (راجع هذا الموضوع)

تحياتي.

تم تعديل بواسطه khaled_prg
6

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

خالد == فيصل قاسم ...

بدون تعليق + 1 laugh.gif

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

انا ارى ان مسألة استخدام الــ GC افضل لانها تتيح للمبرمج التفرغ للشيء المهم الا وهو منطق البرنامج، كما ان الــ GC يقوم باشياء صعب على المبرمج عملها يدويا ، فمسألة تحرير الذاكرة ليست مسألة Reference Count فقط بل انها مسألة استخدام خوارزميات مثلى حتى لايتم تحرير كائن قد نحتاج استخدامه بعد فترة قليلة فقط لان الــ Reference count اصبح يساوي الصفر، وعليه فالبديل هو تصميم برامج بمنطق بسيط يتم فيها تحرير الذاكرة بشكل اعتيادي داخل مثلا الــ Destructors او تصميم برامج نقوم بكتابة GC لها وهذه عملية معقده بحد ذاتها من دون ان نذكر ان هذا لايضمن تطبيق الجامع بشكل متقن او حتى صحيح.

تحياتي

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .