تخصيص الذاكرة بين العمليات

يعمل نظام التشغيل Android على فرضية أنّ الذاكرة الفارغة هي ذاكرة مهدورة. ويحاول استخدام كل الذاكرة المتاحة في جميع الأوقات. على سبيل المثال، يحفظ النظام التطبيقات في الذاكرة بعد إغلاقها حتى يتمكّن المستخدم من التبديل مجددًا إليها بسرعة. لهذا السبب، غالبًا ما تعمل أجهزة Android باستخدام كمية قليلة جدًا من الذاكرة الفارغة. إنّ إدارة الذاكرة أمرٌ حيوي لتوزيع الذاكرة بشكلٍ سليم بين العمليات المهمة للنظام والعديد من تطبيقات المستخدمين.

تتناول هذه الصفحة أساسيات كيفية تخصيص Android للذاكرة للنظام وتطبيقات المستخدم. ويوضّح أيضًا كيفية تفاعل نظام التشغيل مع حالات انخفاض سعة الذاكرة.

أنواع الذكريات

تحتوي أجهزة Android على ثلاثة أنواع مختلفة من الذاكرة: ذاكرة الوصول العشوائي (RAM) وذاكرة zRAM وذاكرة التخزين. تجدر الإشارة إلى أنّ كلّ من وحدة المعالجة المركزية ووحدة معالجة الرسومات يصلان إلى ذاكرة الوصول العشوائي نفسها.

أنواع الذكريات

الشكل 1: أنواع الذاكرة: ذاكرة الوصول العشوائي وذاكرة zRAM ومساحة التخزين

  • ذاكرة الوصول العشوائي هي أسرع أنواع الذاكرة، ولكن حجمها عادةً ما يكون محدودًا. عادةً ما تحتوي الأجهزة المتطوّرة على أكبر كميات من ذاكرة الوصول العشوائي.

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

  • يحتوي قسم "التخزين" على جميع البيانات الثابتة، مثل نظام الملفات ورمز الكائن المضمّن لجميع التطبيقات والمكتبات والنظام الأساسي. تتمتع سعة التخزين بسعة أكبر بكثير من النوعَين الآخرين من الذاكرة. في نظام التشغيل Android، لا يتم استخدام مساحة التخزين لمساحة التخزين المؤقت مثلما هو الحال في عمليات تنفيذ Linux الأخرى، لأنّه يمكن أن تؤدي الكتابة المتكرّرة إلى تلف هذه الذاكرة وتقصير عمر وسيط التخزين.

صفحات الذكريات

يتم تقسيم ذاكرة الوصول العشوائي إلى صفحات. تشغل كل صفحة عادةً 4 كيلوبايت من الذاكرة.

تُعتبر الصفحات إما مجانية أو مستخدَمة. الصفحات الفارغة هي ذاكرة وصول عشوائي غير مستخدَمة. صفحات المعالجة المُستخدَمة هي ذاكرة الوصول العشوائي التي يستخدمها النظام بشكل نشط، ويتم تجميعها في الفئات التالية:

  • الذاكرة المخزَّنة مؤقتًا: الذاكرة التي يكون ملف على مساحة التخزين احتياطيًا لها (مثل الرمز أو الملفات المُعرَّفة بالذاكرة) هناك نوعان من الذاكرة المخزَّنة مؤقتًا:
    • خاص: مملوك لعملية واحدة ولم تتم مشاركته
      • نظيفة: نسخة لم يتم تعديلها من ملف في مساحة التخزين، ويمكن حذفها باستخدام الرمز kswapd لزيادة الذاكرة الفارغة
      • غير محفوظة: نسخة معدَّلة من الملف في مساحة التخزين، ويمكن نقلها إلى zRAM أو ضغطها فيها باستخدام kswapd لزيادة الذاكرة المتوفّرة
    • مشترَكة: تُستخدَم من قِبل عمليات متعدّدة
      • نظيفة: نسخة غير معدَّلة من الملف في مساحة التخزين، ويمكن حذفها باستخدام الرمز kswapd لزيادة الذاكرة المتوفّرة
      • غير محفوظة: نسخة معدَّلة من الملف في مساحة التخزين، تسمح بتسجيل التغييرات مجددًا في الملف في مساحة التخزين لزيادة الذاكرة المتوفّرة باستخدام kswapd أو باستخدام msync() أو munmap()
  • غير محدّد: الذاكرة التي لا تتضمّن ملفًا في مساحة التخزين (على سبيل المثال، تم تخصيصها باستخدام mmap() مع ضبط العلامة MAP_ANONYMOUS)
    • غير صالحة: يمكن نقلها أو ضغطها في zRAM بواسطة kswapd لزيادة الذاكرة الخالية

تختلف نسبة الصفحات الفارغة والمستخدَمة بمرور الوقت لأنّ النظام يديره بشكل نشط ذاكرة الوصول العشوائي. إنّ المفاهيم التي تم تقديمها في هذا القسم هي مفاتيح إدارة المواقف التي تنخفض فيها سعة الذاكرة. ويوضّح القسم التالي من هذا المستند هذه الإعدادات بمزيد من التفصيل.

إدارة الذاكرة المنخفضة

يتضمّن Android آليتين رئيسيتين للتعامل مع حالات انخفاض الذاكرة: ملف التمهيد swap daemon وبرنامج low-memory killer.

برنامج kernel swap daemon

يُعدّ برنامج kernel swap daemon (kswapd) جزءًا من نواة Linux، ويحوّل الذاكرة المُستخدَمة إلى ذاكرة فارغة. يصبح الخادم غير القابل للإنهاء نشطًا عندما تنخفض الذاكرة الفارغة على الجهاز. يحافظ نواة نظام التشغيل Linux على حدود منخفضة وعالية للذاكرة الفارغة. عندما تقلّ الذاكرة الفارغة عن الحدّ الأدنى، يبدأ kswapd في استرداد الذاكرة. بعد أن تصل الذاكرة الفارغة إلى الحدّ الأقصى، يتوقف kswapd عن استرداد الذاكرة.

يمكن kswapd استرداد الصفحات النظيفة من خلال حذفها لأنّه يتم الاحتفاظ بنسخة احتياطية منها في مساحة التخزين ولم يتم تعديلها. إذا حاولت إحدى العمليات الوصول إلى صفحة نظيفة سبق أن تم حذفها، ينسخ النظام الصفحة من مساحة التخزين إلى ذاكرة الوصول العشوائي. تُعرف هذه العملية باسم التنقّل في الذاكرة عند الطلب.

تم حذف صفحة نظيفة مستندة إلى مساحة تخزين

الشكل 2: صفحة نظيفة، تم تخزينها، وتم حذفها

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

إذا انخفضت كمية الذاكرة الفارغة عن حدّ معيّن، يبدأ النظام في إيقاف العمليات.

تم نقل الصفحة غير النظيفة إلى zRAM وضغطها

الشكل 3: تم نقل الصفحة غير النظيفة إلى zRAM وضغطها

ميزة "قتل التطبيقات التي تستهلك ذاكرة منخفضة"

في كثير من الأحيان، لا يمكن لتطبيق kswapd تحرير ذاكرة كافية للنظام. في هذه الحالة، يستخدم النظام onTrimMemory() لإعلام التطبيق بأنّ الذاكرة ستنفد قريبًا وأنّه يجب تقليل موارده المخصّصة. إذا لم يكن ذلك كافيًا، تبدأ النواة في إنهاء العمليات لمحاولة إخلاء الذاكرة. ويستخدم هذا الإجراء أداة LMK (المسؤولة عن إنهاء العمليات التي تستهلك ذاكرة منخفضة) لتنفيذ ذلك.

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

عمليات Android، مع عرض أعلى الأرقام في أعلى الشاشة

الشكل 4: عمليات Android، مع الدرجات العالية في الأعلى والدرجات المنخفضة في الأسفل

في ما يلي أوصاف للفئات المختلفة الواردة في الجدول أعلاه:

  • التطبيقات التي تعمل في الخلفية: هي التطبيقات التي تم تشغيلها سابقًا وليست نشطة حاليًا. ستُغلق ميزة "إدارة الذاكرة الذكية" أولاً التطبيقات التي تعمل في الخلفية، بدءًا من التطبيق الذي يستهلك oom_adj_score.

  • التطبيق السابق: هو التطبيق الذي تم استخدامه مؤخرًا في الخلفية. يحظى التطبيق السابق بأولوية أعلى (نتيجة أقل) من التطبيقات التي تعمل في الخلفية لأنّه من المرجّح أن ينتقل إليه المستخدم بدلاً من أحد التطبيقات التي تعمل في الخلفية.

  • تطبيق Home: هذا هو تطبيق مشغّل التطبيقات. سيؤدي إيقاف هذا التطبيق إلى اختفاء الخلفية.

  • الخدمات: تبدأ التطبيقات الخدمات وقد تشمل المزامنة أو التحميل إلى السحابة الإلكترونية.

  • التطبيقات التي يمكن ملاحظتها: هي التطبيقات التي لا تعمل في المقدّمة، ولكن يمكن للمستخدم ملاحظتها بطريقة ما، مثل تشغيل عملية بحث تعرض واجهة مستخدم صغيرة أو слушаниة الموسيقى.

  • التطبيق الذي يعمل في المقدّمة: هو التطبيق الذي يتم استخدامه حاليًا. إنّ إنهاء تطبيق يعمل في المقدّمة يشبه تعطُّل التطبيق، ما قد يشير إلى المستخدم أنّه يحدث خطأ في الجهاز.

  • التطبيقات الثابتة (الخدمات): وهي الخدمات الأساسية للجهاز، مثل الهاتف وWi-Fi.

  • النظام: عمليات النظام عند إيقاف هذه العمليات، قد يبدو أنّ الهاتف تتم إعادة تشغيله.

  • العمليات الأصلية: عمليات منخفضة المستوى جدًا يستخدمها النظام (مثل kswapd).

يمكن لشركات تصنيع الأجهزة تغيير سلوك LMK.

احتساب مساحة الذاكرة التي يشغلها التطبيق

تتتبّع النواة جميع صفحات الذاكرة في النظام.

الصفحات التي تستخدمها عمليات مختلفة

الشكل 5: الصفحات التي تستخدمها عمليات مختلفة

عند تحديد مقدار الذاكرة التي يستخدمها أحد التطبيقات، يجب أن يأخذ النظام الصفحات المشتركة في الاعتبار. ستتشارك التطبيقات التي تصل إلى الخدمة أو المكتبة نفسها صفحات الذاكرة. على سبيل المثال، قد تتم مشاركة خدمة تحديد الموقع الجغرافي بين "خدمات Google Play" وتطبيق لعبة. ويصعِّب ذلك تحديد مقدار الذاكرة التي تخصّ الخدمة بشكل عام مقارنةً بكل تطبيق.

الصفحات التي يشاركها تطبيقان

الشكل 6: الصفحات التي يشاركها تطبيقان (في الوسط)

لتحديد مساحة الذاكرة التي يشغلها تطبيق معيّن، يمكن استخدام أيّ من المقاييس التالية:

  • حجم المجموعة الثابتة (RSS): عدد الصفحات المشتركة وغير المشتركة التي يستخدمها التطبيق
  • حجم المجموعة النسبي (PSS): عدد الصفحات غير المشتركة التي يستخدمها التطبيق وتوزيع متساوٍ للصفحات المشتركة (على سبيل المثال، إذا كانت ثلاث عمليات تشارك 3 ميغابايت، تحصل كل عملية على 1 ميغابايت في PSS)
  • حجم المجموعة الفريدة (USS): عدد الصفحات غير المشتركة التي يستخدمها التطبيق (لا يتم تضمين الصفحات المشتركة)

تكون ذاكرة PSS مفيدة لنظام التشغيل عندما يريد معرفة مقدار الذاكرة التي يتم استخدامها من قِبل جميع العمليات، لأنّه لا يتم احتساب الصفحات عدة مرات. يستغرق احتساب PSS وقتًا طويلاً لأنّ النظام يحتاج إلى تحديد الصفحات التي تتم مشاركتها وعدد العمليات التي تتم مشاركتها. لا يميز RSS بين الصفحات المشترَكة والصفحات غير المشترَكة (ما يجعل عملية احتسابه أسرع)، وهو أفضل لتتبُّع التغييرات في تخصيص الذاكرة.

مصادر إضافية