التخزين المؤقت المضمن

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

ربط أساليب وقت التشغيل

تستقبل دالة ECMAScript التالية كائنًا، وتستدعي طريقة toString الخاصة به، وتعرض النتائج على الصفحة التي تم تضمين البرنامج النصي فيها.

function dump ( obj ) { document . write ( obj . toString ()); }

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

لتحقيق أداء أفضل، تستخدم العديد من بيئات تشغيل اللغات نوعًا من التخزين المؤقت غير المضمن، حيث تُخزَّن نتائج عدد محدود من عمليات البحث عن الدوال في بنية بيانات ترابطية . يمكن لهذا أن يزيد الأداء بشكل كبير، شريطة أن تكون البرامج المنفذة "متوافقة مع التخزين المؤقت" (أي أن هناك مجموعة محدودة من الدوال التي يتم استدعاؤها بشكل متكرر). تُسمى بنية البيانات هذه عادةً ذاكرة التخزين المؤقت للبحث عن الدوال من المستوى الأول . [ 1 ]

التخزين المؤقت المضمن

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

التنفيذ النموذجي [ 1 ] هو تحميل قيمة ثابتة في سجل، متبوعًا بتعليمات استدعاء. يُفضل تسمية الحالة "غير المُهيأة" بـ"غير المرتبطة". يُحمّل السجل بمحدد الرسالة (عادةً عنوان كائن ما)، ويتم استدعاء روتين وقت التشغيل الذي يبحث عن الرسالة في فئة المُستقبِل الحالي، باستخدام ذاكرة التخزين المؤقت للبحث عن الأساليب من المستوى الأول المذكورة أعلاه. ثم يُعيد روتين وقت التشغيل كتابة التعليمات، مُغيرًا تعليمات التحميل لتحميل السجل بنوع المُستقبِل الحالي، وتعليمات الاستدعاء لاستدعاء مقدمة الأسلوب المستهدف، ما يؤدي الآن إلى "ربط" موقع الاستدعاء بالأسلوب المستهدف. يستمر التنفيذ مباشرةً بعد المقدمة. في التنفيذ اللاحق، يتم استدعاء المقدمة مباشرةً. بعد ذلك، تستنتج المقدمة نوع المُستقبِل الحالي وتقارنه بالنوع الموجود في السجل؛ إذا تطابقا، يكون المُستقبِل من نفس النوع، ويستمر تنفيذ الأسلوب. وإلا، فإن الديباجة تستدعي وقت التشغيل مرة أخرى وتكون هناك استراتيجيات مختلفة ممكنة، إحداها إعادة ربط موقع الاتصال بنوع جهاز الاستقبال الجديد.

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

التخزين المؤقت المضمن أحادي الشكل

إذا كان موقع استدعاء معين يشهد أنواعًا مختلفة من الكائنات بشكل متكرر، فقد تُفقد فوائد الأداء للتخزين المؤقت المضمن بسهولة بسبب العبء الزائد الناتج عن التغييرات المتكررة في حالة موقع الاستدعاء. يُمثل المثال التالي أسوأ سيناريو للتخزين المؤقت المضمن أحادي الشكل:

var values ​​= [ 1 , "a" , 2 , "b" , 3 , "c" , 4 , "d" ]; for ( var i in values ​​) { document . write ( values ​​[ i ]. toString ()); }

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

التخزين المؤقت المضمن متعدد الأشكال

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

التنفيذ النموذجي [ 2 ] عبارة عن جدول قفز يتألف من مقدمة تحدد نوع المُستقبِل، وسلسلة من المقارنات الثابتة والقفزات الشرطية التي تنتقل إلى الكود الذي يلي المقدمة في الدالة المناسبة لكل نوع مُستقبِل. يُخصَّص جدول القفز عادةً لموقع استدعاء مُحدد عندما يُصادف موقع استدعاء أحادي الشكل نوعًا مختلفًا. يكون لجدول القفز حجم ثابت، ولكنه قابل للتوسع بإضافة حالات عند مُصادفة أنواع جديدة حتى حد أقصى صغير لعدد الحالات، مثل 4 أو 6 أو 8. بمجرد وصوله إلى حجمه الأقصى، يتوقف التنفيذ لنوع مُستقبِل جديد وينتقل إلى وقت التشغيل، عادةً لإجراء بحث عن دالة بدءًا من ذاكرة التخزين المؤقت للدوال من المستوى الأول.

أدت الملاحظة بأن ذاكرة التخزين المؤقت المضمنة أحادية الشكل ومتعددة الأشكال تجمع معلومات نوع المتلقي لكل موقع استدعاء كأثر جانبي لتحسين تنفيذ البرنامج [ 2 ] إلى تطوير التحسين التكيفي في Self ، حيث يقوم وقت التشغيل بتحسين "النقاط الساخنة" في البرنامج باستخدام معلومات النوع في ذاكرة التخزين المؤقت المضمنة لتوجيه قرارات التضمين التخميني.

التخزين المؤقت المضمن ذو الشكل الضخم

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

تُظهر القياسات التجريبية [ 3 ] أنه في برامج Smalltalk الكبيرة، يظل حوالي 1/3 من جميع مواقع الإرسال في الطرق النشطة غير مرتبطة، ومن الـ 2/3 المتبقية، 90% أحادية الشكل، و9% متعددة الأشكال، و1% (0.9%) ضخمة الشكل.

انظر أيضاً

مراجع

  1. 1 2 3 ل. بيتر دويتش، آلان م. شيفمان، "التنفيذ الفعال لنظام سمول توك-80"، POPL '84: وقائع الندوة الحادية عشرة لجمعية ACM SIGACT-SIGPLAN حول مبادئ لغات البرمجة، يناير 1984
  2. 1 2 3 هولزلي، يو.، تشامبرز، سي.، وأونغار، دي. 1991. تحسين لغات البرمجة الكائنية ذات الكتابة الديناميكية باستخدام ذاكرة التخزين المؤقت المضمنة متعددة الأشكال. في وقائع مؤتمر ECOOP '91. سلسلة محاضرات في علوم الحاسوب، المجلد 512. سبرينغر-فيرلاغ، برلين.
  3. صور [ انطباعات أولية عن الإصدار 8 ] على القائمة البريدية لـ Strongtalk