# ذاكرة مخبئية

الخابية أو الذاكرة المخبئية (بالإنجليزية: Cache)‏ هي مبدأ في المعلوماتية يستعمل مقوما لحفظ البيانات بشكل يسمح بإسترجاعها بشكل أسرع في الطلبات اللاحقة، وقد تكون هذه البيانات نسخا من بيانات أصلية مخزنة في مكان آخر، أو قيم تم حسابها مسبقا، فإذا كانت البيانات المطلوبة موجودة في الذاكرة المخبأة فإنه يمكّن الاستجابة للطلب بقراءة البيانات من الذاكرة المخبأة، والتي تكون القراءة منها أسرع بالمقارنة مع محاولة قراءتها من مخزنها الأصلي أو إعادة حسابها، تاريخياً وحدة المعالجة المركزية كانت دائما أسرع من الذواكر في إدخال وإخراج البيانات. وبالرغم من سير مراحل تطوير الذواكر بشكل موازي مع عملية تطوير المعالجات. إلا أنه كان بينهما دائماً فرق في سرعة الاداء لصالح وحدة المعالجة المركزية. فبعد أن تطلب وحدة المعالجة المركزية المعلومات من الذاكرة الرئيسية تبقى وحدة المعالجة المركزية منتظرة لإستجابة الذاكرة الرئيسية - وفي أفضل الأحوال كانت الذاكرة المخبأة تنتظر من 2 إلى 3 دورات (دورة الناقل) حتى تصلها المعلومات، وكان استخدام ذاكرة سريعة قادرة على الاستجابة بسرعة أقرب لسرعة طلبات وحدة المعالجة المركزية وإستغلالها لتخزين البيانات التي تم طلبها مؤخرا طريقة لتجنب ضياع الوقت في انتظار جلب البيانات من مكان تخزينها.
بالرغم من إمكانية إنتاج ذواكر سريعة تماشي سرعة طلب وحدة المعالجة المركزية للبيانات، إلا أن عقبة اقتصادية تواجه إنجاز مثل هذا التصميم لا عقبة تقنيّة. إن المتخصصين في هذا المجال يعرفون كيفية بناء ذواكر سريعة بحيث تكون سرعتها متوافقة مع سرعة الذاكرة المخبأة للتخلص من الوقت الضائع في دورة الناقل، لكن المشكلة في التكلفة المرتفعة لهذا النوع من الذواكر وسيكون من المكلف جداً تجهيز حاسوب مع هذا النوع من الذواكر.
وهكذا، كان هناك خياران أمام مهندسي التصميم، الأول هو استخدام تلك الذواكر السريعة ذات الكلفة العالية، والثاني استخدام ذاكرة رخيصة الثمن وذات سرعة بطيئة. فكان الاختيار بأخذ خاصية السرعة من الجانب الأول وخاصية الكلفة المنخفضة من الجانب الآخر ودمجت هذه الخواص لإنتاج الذواكر السريعة ذات الحجم الصغير (للتقليل من الكلفة) وسميت بالذاكرة المخبأة Cache Memory $^{[لغاتأخرى]}$‏.
الذاكرة المؤقتة «كاش Cache» ذاكرة سريعة الأداء تعمل بمثابة أداة وسيطة بين وحدة المعالجة والذاكرة المركزية، وهي تستعمل لتخزين مجموعات معينة من التعليمات المعدة للاستخدام الفوري، ويحتفظ المتصفح Browser مثل (نافيغيتور أو اكسبلورر) بذاكرة مؤقتة من الملفات لمساعدتك على تسريع تصفحك الإنترنت. وتعتبر الذاكرة المخبأة للمتصفح بمثابة مجلد موجود في الهارد ديسك، حيث يختزن فيها بشكل مؤقت نسخاً من الملفات التي تختارها من الإنترنت أثناء التصفح، وحين تعود إلى صفحة من الصفحات التي قمت بزيارتها مؤخرًا، فإن المتصفح يستطيع أن يعيد استدعاء Reload هذه الصفحة في الحال بدلاً من الذهاب إلى الويب (الإنترنت) وجلبها من جديد، وكأنك في هذه الحالة تحتفظ بنسخة من مستند في مكتبك بدلاً من الذهاب إلى المكتبة للحصول على أصل المستند نفسه.

## تنظيم الذاكرة المخبأة

يحتوي كل موقع في الذاكرة المخبأة كلمة واحدة، وهذا الموقع هو في الواقع صورة لموقع موجود في الذاكرة الرئيسية. بالإضافة لذلك، يجب أن تتضمن كلمة الذاكرة المخبأة عنوان الموقع المقابل في الذاكرة الرئيسية، إذ يستخدم هذا العنوان عند محاولة الرجوع إلى الذاكرة، لمعرفة إذا كان للموقع المقصود صورة في الذاكرة المخبأة. يمكن أن يتم نسخ كلمة من الذاكرة الرئيسية إلى الذاكرة المخبأة بطريقتين:
* التقابل المباشر أو الثابت (Fixed or Direct mapping)
* التقابل الحر أو الترابطي (Free or associative mapping

## الذاكرة المخبأة المنظومة قطاعاتٍ

تنظم الذاكرة، وكذلك أيضا الذاكرة المخبأة، على شكل قطاعات (Sectors)، ويتألف كل قطاع من عدة كتل، والتقابل بين القطاعات في الذاكرتين من النوع الحر. لكل قطاع في الذاكرة المخبأة وسم عنونة (Address tag)، أما عنوان الكتلة في الذاكرة المخبأة فهو مطابق لعنوانها في الذاكرة. تنقل المعلومات من الذاكرة إلى الذاكرة المخبأة على شكل كتلة في كل مرة ولا ينقل القطاع بأكمله، وبالتالي يمكن أن يحتوي القطاع في الذاكرة المخبأة عدة كتل فارغة، ويمكن ألا يتضمن القطاع إلا كتلة واحدة فقط. للتمييز بين الكتل الفارغة والكتل المشحونة نستخدم لكل كتل بت إضافية نسميها بت الصلاحية (Validity bit)، فإذا كانت هذه البت تحتوي القيمة 1 تكون الكتلة الموافقة موجودة وصالحة للاستخدام.
عند طلب الوصول إلى كتلة يتم أولاً التحقق من وجود عنوان القطاع الموافق في الذاكرة الترابطية، فإذا وجد هذا القطاع يجب اختبار قيمة بت الصلاحية للكتلة في القطاع، فإذا كانت هذه القيمة تساوي الواجد تكون الكتلة موجودة في الذاكرة المخبأة وصالحة للاستخدام وإلا يتولد «خطأ الكتلة» مما يستلزم نقل الكتلة المطلوبة من الذاكرة الرئيسية وتسند بعدها القيمة 1 لبت الصلاحية.
أما إذا لم يكن عنوان القطاع موجودا في الذاكرة الترابطية فيتولد «خطأ القطاع» مما يعني ضرورة الرجوع إلى الذاكرة الرئيسية لجلب القطاع، وقد يطلب الأمر استبعاد أحد القطاعات من الذاكرة المخبأة لإفساح المجال للقطاع الجديد وينتقى القطاع المستبعد بالاعتماد على المعيار المناسب.
لكن خطأ القطاع لن يؤدي لجلب القطاع بأكمله من الذاكرة، ولا تنقل إلا الكتلة المطلوبة منه. بعد نقل القطع تسند القيمة 1 لبت الصلاحية الموافق له، أما بتات صلاحية الكتل الأخرى في هذا القطاع فتضبط على القيمة 0 إشارة لعدم صلاحيتها، فهي من بتات القطاع المنقول سابقا والذي تم استبعاده.
تمتاز طريقة التنظيم هذه ببساطتها الناتجة عن تقليص عدد مداخل الذاكرة الترابطية، إذ تستخدم علامة عنونة وحيدة لكل قطاع بدلا من علامة لكل كتلة كما يتقلص أيضا عدد بتات كل مدخل لأن عناوين القطاعات اصغر من عناوين الكتل فالذاكرة تحوي عددا من القطاعات اقل من عدد الكتل، أما أهم مساوي هذه الطريقة فهي أن جزءاً هاماً من الذاكرة الترابطية قد يكون في أي لحظة مشغولاً بكتل غير صالحة للاستخدام.

### مميزات الطرق المختلفة في تنظيم الذاكرة المخبأة

تلخص الصورة التالية أهم مميزات الأنماط السابقة، ويبين الشكل (13-11) مخطط التقابل المستخدم في كل طريقة من هذه الطرق ويوضح الشكل كيف أن بعض الطرق ليست إلا حالات خاصة محدودة من طرق أخرى.

### استبدال الكتل أو الكلمات

عندما تولد الذاكرة المخبأة خطأ الكلمة (أو خطأ الكتلة أو خطأ القطاع) يجب تفريغ كلمة (أو كتلة أو قطاع) لاستيعاب الجديدة. ولانتقاء الوحدة الواجبة استيعابها يمكن الاعتماد على عدة إستراتيجيات، منها:
* الخيار العشوائي
* الرتل FIFO (من يدخل أولا يخرج أولا)
* الوحدة الأقل استخداماَ في الماضي Least recently used
والإستراتجية الأخيرة هي الأكثر شيوعا في التطبيق.

### الكتابة في الذاكرة المخبأة

عندما تكون الكتلة المطلوبة الموجودة في الذاكرة المخبأة، تقرأ منها دون الرجوع إلى الذاكرة، إلا أنه عند تنفيذ عملية كتابة (write) يجب الولوج إلى الذاكرة حتى لو كانت موجودة في الذاكرة المخبأة. فإذا كان للموقع الذي نكتب فيه في الذاكرة صورة في الذاكرة المخبأة يجب اختيار أحد إجراءين:
* الكتابة الآنية (Write through): أي تكتب المعلومات في الذاكرة وفي الذاكرة المخبأة بنفس الوقت (وهي الطريقة التي وصفناها سابقا).
* الكتابة المتأخرة (Write back): لا ينعكس التغيير الذي طرأ على الموقع الموجود في الذاكرة المخبأة، على الموقع المقابل في الذاكرة إلا عند استبعاد الكلمة من الذاكرة المخبأة.2

#### الكتابة الآنية

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

#### الكتابة المتأخرة

تبقى الكلمة الآنية الصلبة في الذاكرة على حالها ولا يجري التعديل إلا عندما نحتاج لاستبعاد الكتلة الموافقة من الذاكرة المخبأة. نلاحظ هنا أنه في حال بقيت الكتلة كما هي في الذاكرة المخبأة، أي لم تبدل محتوياتها، فإن الذاكرة تحتوي المعطيات الصحيحة ولا داعي لإعادة نقلها من الذاكرة المخبئية.
المخبئية والذاكرة الرئيسية على الترتيب، يصبح عندئذ زمن الولوج الفعلي:
نشير هنا أن $Tap$ هو زمن ولوج الذاكرة محسوباً بعد الأخذ بعين لاعتبار تأثير عملية نقل الصفحات فيحال استخدام الذاكرة الظاهرية، ويعتمد هذا الزمن بالطبع على الإستراتيجية المستخدمة لاستبدال الصفحات
يقترب زمن الولوج الفعلي $Teff$ من زمن ولوج الذاكرة المخبأة $Tac$ كلما اقترب h من الواحد، أي كلما ارتفعت نسبة الإصابة (ويحدث ذلك مثلاً بأخذ خابية ذات حجم كبير جداً).
نلاحظ أن تناقص نسبة الإصابة بنسبة واحدة بالمائة يؤدي إلى زيادة الزمن الفعلي بعدد من المرات يساوي تقريباً النسبة k، ومنه نستنتج أن ثمن فقدان المعطيات المطلوبة من الذاكرة المخبأة عالٍ نوعاً ما من حيث تأثيره على زمن عمل الآلة.
من الوسائط الأخرى التي تؤثر على فعالية الذاكرة المخبأة حجم أو سعة الكتلة، وتأثير هذا الوسيط مشابه لتأثير حجم الصفحة على فعالية الذاكرة الظاهرية.
من الصعب جداً جمع معلومات عن تأثير هذه الوسائط في أوضاع التشغيل الحقيقية، ومن الصعب جداً استخدام دارات إلكترونية لمراقبة أداء الذاكرة الافتراضية لان مثل هذه الدارات يجب أن تكون أسرع بكثير من الآلة نفسها.
غلا انه من المكن استخدام برامج لمحاكاة عمل الآلة عند تنفيذها لعمل نمط تقليدي، لكن تعترض هذا المنهج مشكلتان: ففي البداية تكون الذاكرة المخبأة فارغة، وتبدي نتيجة لذلك فعالية منخفضة جداً إذ سيظهر عدد كبير من حالات فقدان المعطيات. يطلق على هذا الوضع اسم«الحالة العابرة البدائية»(initialization transient).
وتعتمد مدة هذه الحالة العابرة على حجم الذاكرة المخبأة، فكلما ازداد هذا الحجم طالت مدة الحالة العابرة، إن عدد حالت فقدان المعطيات التي تحدث في بداية التشغيل هو تقريباً من نفس سعة مرتبة سعة الذاكرة المخبئية. لذا، وبهدف الحصول على نتائج موثوقة يجب مراقبة أداء الذاكرة لمدة كافية حتى يحدث على الأقل $100*n$ حالة فقدان معطيات (حيث $n$ سعة الذاكرة المخبأة) فإذا حصلنا على نسبة فقدان تساوي واحد بالمائة، يجب إنجاز حوال $10000*n$ عملية رجوع للذاكرة.