يتضمّن الإصدار 17 من نظام التشغيل Android والإصدارات الأحدث ميزة "محدِّد الذاكرة"، وهي خدمة تابعة لنظام التشغيل تراقب استخدام الذاكرة في عمليات التطبيقات وتحدّ منه باستخدام الإصدار 2 من مجموعة التحكّم في Linux. تمنع ميزة "محدِّد الذاكرة" التطبيقات الفردية من استهلاك ذاكرة النظام بشكل غير متناسب، ما يقلّل من الضغط الإجمالي على الذاكرة ويمنع عمليات الإيقاف القسري للعمليات المهمة في المقدّمة والعمليات المخزَّنة مؤقتًا بسبب انخفاض الذاكرة.
الآلية
يتكامل "محدِّد الذاكرة" مع خدمة Activity Manager Service (AMS) لتتبُّع أحداث مراحل العمليات وتغييرات الحالة. تفرض ميزة "محدِّد الذاكرة" حدودًا على الذاكرة باستخدام التسلسل الهرمي لمجموعة التحكّم (cgroup) الإصدار 2 في نواة Linux.
لإتاحة ميزة "الحدّ من استهلاك الذاكرة"، يجب أن تفعّل نواة الجهاز الإصدار 2 من cgroup ووحدة التحكّم memory. تعتمد الخدمة تحديدًا على السمات التالية:
memory.high- حدّ أقصى مرن: وعند تجاوز هذا الحدّ، يتم تقييد العملية وتحاول النواة استعادة الصفحة بشكل استباقي من تلك العملية.
memory.swap.max- يحدّد هذا الإعداد الحد الأقصى لمساحة الإبدال (مثل ZRAM) التي يمكن للعملية استخدامها.
التأثير في التطبيقات
لا تتأثر التطبيقات التي تعمل ضمن حدود الذاكرة المسموح بها بميزة "محدِّد الذاكرة".
عندما يتجاوز التطبيق الحدّ الأقصى المسموح به وهو memory.high، تُزيل النواة الذاكرة النظيفة للتطبيق المستندة إلى الملفات وتستبدل الذاكرة المجهولة غير النشطة لإبقاء التطبيق ضمن الحدّ الأقصى. نتيجةً لعملية إخلاء الصفحات وتبديلها، قد يواجه التطبيق تقييدًا مؤقتًا في التنفيذ، ولكنه يستمر في العمل.
في الحالات القصوى، مثل تسرُّب الذاكرة غير الخاضع للتحكّم حيث يستمر التطبيق في تخصيص ذاكرة مجهولة بعد نفاد مساحة الإبدال، يتعذّر على التطبيق تخصيص الذاكرة ويتم إنهاؤه.
مراقبة العمليات
يراقب "محدِّد الذاكرة" عمليات التطبيقات (UID >= 10000) تلقائيًا. ويتم استثناء عمليات النظام الأساسية للحفاظ على استقرار النظام الأساسي.
تحدّد ميزة "التحكّم في الذاكرة" حدودًا للذاكرة استنادًا إلى حالة ظهور العملية:
العمليات المرئية: هي العمليات التي تستضيف واجهة مستخدم مرئية للمستخدم (مثل النشاط الذي يتم التركيز عليه حاليًا أو التفاعل النشط). بما أنّ عرض واجهة المستخدم يتطلّب مجموعة عمل أكبر لعمليات العرض ومسارات الرسومات، تحصل العمليات المرئية على حدّ ذاكرة أكبر.
العمليات غير المرئية: هي العمليات التي تؤدي مهامًا في الخلفية بدون عرض واجهة مستخدم (مثل الخدمات التي تُشغَّل في الخلفية أو مستقبلات البث). وبما أنّها لا تعرض مكوّنات واجهة المستخدم، فإنّها تعمل ضمن حدّ أكثر تقييدًا.
يوضّح الجدول التالي حالات معيّنة للعمليات وفقًا لتصنيفات حدود الذاكرة:
| حالة العملية | الحدّ الأقصى للذاكرة |
|---|---|
PERSISTENT | غير محدود |
PERSISTENT_UI | غير محدود |
TOP | Visible |
BOUND_TOP | Visible |
FOREGROUND_SERVICE | غير مرئية |
BOUND_FOREGROUND_SERVICE | غير مرئية |
IMPORTANT_FOREGROUND | Visible |
IMPORTANT_BACKGROUND | غير مرئية |
TRANSIENT_BACKGROUND | غير مرئية |
BACKUP | غير مرئية |
SERVICE | غير مرئية |
RECEIVER | غير مرئية |
TOP_SLEEPING | Visible |
HEAVY_WEIGHT | غير مرئية |
HOME | غير مرئية |
LAST_ACTIVITY | غير مرئية |
CACHED_ACTIVITY | نسخة مخبأة |
CACHED_ACTIVITY_CLIENT | نسخة مخبأة |
CACHED_RECENT | نسخة مخبأة |
CACHED_EMPTY | نسخة مخبأة |
في حالة التخزين المؤقت، يتم تجميد العمليات ثم استعادتها إلى أقصى حد.
عندما تتجاوز عملية ما الحدّ الأقصى المخصّص لها من memory.high، ترصد ميزة "محدِّد الذاكرة"
هذا الحدث ويمكنها بدء إجراءات تشخيصية، مثل تسجيل
ملف تعريف الذاكرة أو تسجيل قيمة شاذة في statsd.
الإعداد
في الإصدار 17 من Android والإصدارات الأحدث، يتم ضبط "محدِّد الذاكرة" باستخدام ملف إعداد النظام الأساسي العادي في قسم النظام على المسار /system/etc/memory-limiter-config.xml.
تنسيق XML
يتّبع ملف الإعداد المخطط المحدّد في
memory-limiter-config.xsd. يحدّد الملف مجموعات حدود متعددة مرتّبة حسب الذاكرة المتاحة، وتختار الخدمة أعلى مجموعة حدود مطابقة استنادًا إلى ذاكرة الوصول العشوائي المتاحة على الجهاز. يتم تحديد جميع قيم الذاكرة بالميغابايت (MiB).
<MemoryLimiterConfig>
<version>1</version>
<configList>
<!-- RAM boundaries account for MemTotal excluding carve-outs. -->
<limitSet>
<!-- Limits for 16GB RAM device [14336, 18432): 10G/5G/5G/5G -->
<minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
<maximumAllowedMemTotal>18432</maximumAllowedMemTotal>
<memVisible>10240</memVisible>
<memNotVisible>5120</memNotVisible>
<swapVisible>5120</swapVisible>
<swapNotVisible>5120</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 12GB RAM device [9216, 14336): 8G/4G/4G/4G -->
<minimumRequiredMemTotal>9216</minimumRequiredMemTotal>
<maximumAllowedMemTotal>14336</maximumAllowedMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 8GB RAM device [6800, 9216): 5G/3G/3G/3G -->
<minimumRequiredMemTotal>6800</minimumRequiredMemTotal>
<maximumAllowedMemTotal>9216</maximumAllowedMemTotal>
<memVisible>5120</memVisible>
<memNotVisible>3072</memNotVisible>
<swapVisible>3072</swapVisible>
<swapNotVisible>3072</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 6GB RAM device [4800, 6800): 4G/2G/2G/2G -->
<minimumRequiredMemTotal>4800</minimumRequiredMemTotal>
<maximumAllowedMemTotal>6800</maximumAllowedMemTotal>
<memVisible>4096</memVisible>
<memNotVisible>2048</memNotVisible>
<swapVisible>2048</swapVisible>
<swapNotVisible>2048</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 4GB RAM device [3200, 4800): 2G/1G/1G/1G -->
<minimumRequiredMemTotal>3200</minimumRequiredMemTotal>
<maximumAllowedMemTotal>4800</maximumAllowedMemTotal>
<memVisible>2048</memVisible>
<memNotVisible>1024</memNotVisible>
<swapVisible>1024</swapVisible>
<swapNotVisible>1024</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- عدد صحيح موجب يحدّد إصدار الإعدادات يجب أن تكون هذه القيمة
1. minimumRequiredMemTotalالحد الأدنى لذاكرة النظام
MemTotal(بالميغابايت، الحد الأدنى الشامل) المطلوب لتطبيق مجموعة الحدود هذه. وتقيّم الخدمة هذا المقياس مقارنةً بإجمالي الذاكرة المتاحة التي تظهر في النواة في/proc/meminfo.فهم عمليات اقتطاع الذاكرة وحدودها: تعكس قيمة النواة
MemTotalذاكرة الوصول العشوائي الديناميكية (DRAM) الفعلية التي يمكن لنظام التشغيل الوصول إليها بعد خصم عمليات اقتطاع ذاكرة الأجهزة والبرامج الثابتة. تحجز عمليات الاقتطاع ذاكرة الوصول العشوائي (RAM) لمكوّنات الأجهزة المتخصّصة، مثل وحدة معالجة الرسومات (GPU) ومودم النطاق الأساسي ومزوّد خدمة الإنترنت (ISP) للكاميرا وبيئات التنفيذ الآمنة وبرامج مراقبة الأجهزة الافتراضية، وتستهلك عادةً ما بين 500 ميبي بايت وأكثر من 2 غيبي بايت من الذاكرة الفعلية.بما أنّ قيمة
MemTotalأقل من ذاكرة DRAM الفعلية المُعلَن عنها للجهاز، تتضمّن حدودminimumRequiredMemTotalهامشًا لهذه الاستثناءات. على سبيل المثال، يحدّد الإعداد الذي يستهدف الأجهزة بسعة 16 غيغابايت حدًا أدنى يبلغ14336(14 غيبي بايت) بدلاً من16384(16 غيبي بايت)، ويحدّد الإعداد الذي يستهدف الأجهزة بسعة 12 غيغابايت حدًا أدنى يبلغ9216(9 غيبي بايت). يضمن ذلك أن يتطابق كل جهاز مع الفئة المخصصة له بغض النظر عن الاختلافات في الاستثناءات على مستوى اللوحة.maximumAllowedMemTotalالحد الأقصى لـ
MemTotalفي النظام (بالميغابايت، الحد الأقصى الحصري) الذي يتم تطبيق هذا الحد عليه. إذا كانت قيمةMemTotalأكبر من أو تساوي هذا الحد الأقصى، لا ينطبق الحدّ المعيّن. بالنسبة إلى الأجهزة التي تبلغ سعة ذاكرتها 18,432 مبيبايت أو أكثر أو الأجهزة التي تبلغ سعة ذاكرتها أقل من 3,200 مبيبايت، لا يفرض "محدِّد الذاكرة" أي قيود، ما يترك العمليات بدون قيود.memVisibleالحدّ الأقصى المرن للذاكرة (
memory.high) بالميغابايت الثنائي (MiB) المطبَّق على العمليات المرئية.memNotVisibleالحدّ الأقصى المرن للذاكرة (
memory.high) بالميغابايت المطبَّق على العمليات غير المرئيةswapVisibleالحدّ الأقصى لمساحة الإبدال (
memory.swap.max) بالميغابايت المطبَّق على العمليات المرئية.swapNotVisibleالحدّ الأقصى لمساحة الإبدال (
memory.swap.max) بالميغابايت المطبَّق على العمليات غير المرئية
الحدود القصوى العادية للمنصة
في الإصدار 17 من نظام التشغيل Android والإصدارات الأحدث، يحدّد النظام الأساسي حدودًا عادية للذاكرة ومساحة التخزين المؤقت
في /system/etc/memory-limiter-config.xml على مستوى فئات ذاكرة الوصول العشوائي (RAM) الفعلية الشائعة
باستخدام فواصل نطاق [floor, ceiling):
| ذاكرة الوصول العشوائي (RAM) المادية المستهدَفة |
نطاق MemTotal [الحد الأدنى، الحد الأقصى) (minimumRequiredMemTotal, maximumAllowedMemTotal) |
الحدّ الأقصى للذاكرة المرئية (memVisible) |
الحدّ الأقصى للذاكرة غير المرئية (memNotVisible) |
الحدّ الأقصى لعدد عمليات التبديل المرئية (swapVisible) |
الحد الأقصى لعدد عمليات التبديل غير المرئية (swapNotVisible) |
|---|---|---|---|---|---|
| 16 غيغابايت | [14336, 18432) ميبيبايت |
10,240 ميغابايت (10 غيبي بايت) | 5,120 ميبيبايت (5 غيبي بايت) | 5,120 ميبيبايت (5 غيبي بايت) | 5,120 ميبيبايت (5 غيبي بايت) |
| 12 غيغابايت | [9216, 14336) ميبيبايت |
8,192 ميبي بايت (8 غيبي بايت) | 4,096 ميغابايت (4 غيبي بايت) | 4,096 ميغابايت (4 غيبي بايت) | 4,096 ميغابايت (4 غيبي بايت) |
| 8 غيغابايت | [6800, 9216) ميبيبايت |
5,120 ميبيبايت (5 غيبي بايت) | 3,072 ميبيبايت (3 غيبي بايت) | 3,072 ميبيبايت (3 غيبي بايت) | 3,072 ميبيبايت (3 غيبي بايت) |
| 6 غيغابايت | [4800, 6800) ميبيبايت |
4,096 ميغابايت (4 غيبي بايت) | 2,048 ميبي بايت (2 غيبي بايت) | 2,048 ميبي بايت (2 غيبي بايت) | 2,048 ميبي بايت (2 غيبي بايت) |
| 4 غيغابايت | [3200, 4800) ميبيبايت |
2,048 ميبي بايت (2 غيبي بايت) | 1,024 ميبيبايت (1 غيبي بايت) | 1,024 ميبيبايت (1 غيبي بايت) | 1,024 ميبيبايت (1 غيبي بايت) |
مبادئ الحدّ الأقصى للذاكرة
تم تصميم إعدادات "محدِّد الذاكرة" استنادًا إلى مبادئ المنصة التالية:
اتساق المنظومة المتكاملة وتوافق التطبيقات: يضمن توحيد حدود الذاكرة على جميع الأجهزة أداء التطبيقات المتوقع في جميع أنحاء منظومة Android المتكاملة. يتم تطوير التطبيقات واختبارها وفقًا لتوقعات الذاكرة العادية، ويؤدي الحفاظ على حدود موحّدة للنظام الأساسي إلى تجنُّب حدوث أي تقييد غير متوقَّع أو إنهاء مبكر.
تخصيص الموارد بشكل متناسب: تتم معايرة حدود المنصة وفقًا لسعة ذاكرة الوصول العشوائي (RAM) المادية:
- العمليات المرئية: يتم تخصيص ما يتراوح بين نصف وثلثي إجمالي ذاكرة الوصول العشوائي (RAM) الفعلية لدعم واجهة المستخدم النشطة وعمليات الدمج وأعباء عمل العرض.
- العمليات غير المرئية: يتم تخصيص ما يقرب من 1/4 إلى 1/3 من إجمالي ذاكرة الوصول العشوائي (RAM) الفعلية للمهام التي يتم تنفيذها في الخلفية.
إمكانية التطبيق الشامل: تنطبق الحدود بشكل موحّد على جميع عمليات التطبيقات على الجهاز (UID >= 10000)، بما في ذلك تطبيقات النظام المثبّتة مسبقًا وتطبيقات المصنّع الأصلي للجهاز. لا تتيح ميزة "محدِّد الذاكرة" استخدام القوائم المسموح بها لاستثناء تطبيقات معيّنة، ما يضمن إدارة عادلة للذاكرة في جميع التطبيقات. لضبط الحد الأدنى من الحماية
memory.minذاتية الضبط على برامج الخلفية التفاعلية المهمة والحد الأقصى الأكثر صرامةmemory.highالذي تمت معايرته حسب أعباء العمل على تطبيقات وخدمات النظام الفردية، يُرجى الاطّلاع على ميزانيات ذاكرة النظام.غياب واجهات برمجة التطبيقات لطلبات البحث في وقت التشغيل: في الإصدار 17 من نظام التشغيل Android والإصدارات الأحدث، لا يمكن للتطبيقات الاستعلام آليًا عن حدود الذاكرة المخصّصة لها في وقت التشغيل. يتم تحديد حدود المنصة العادية بهوامش كبيرة لكي تعمل التطبيقات التي تلتزم بالسياسات بدون قيود أثناء الاستخدام العادي.
ديناميكيات استعادة النواة والمبادلة: عندما تقترب عملية تطبيق من الحدّ الأقصى المسموح به في
memory.high، توجّه نواة Linux استعادة الذاكرة تحديدًا إلى مجموعة التحكم في هذه العملية. ويشمل ذلك تجاهل الصفحات غير النشطة المستندة إلى الملفات وتبديل الصفحات المجهولة غير النشطة إلى ZRAM، ما يحافظ على سلاسة النظام بدون فرض ضغط على الذاكرة العامة.
أوامر Shell
يتيح الأمر am memory-limiter للمطوّرين ومُدمجي الأنظمة التفاعل مع الخدمة في وقت التشغيل لأغراض التطوير والاختبار وتصحيح الأخطاء:
am memory-limiter <SUB-COMMAND>status
يعرض الأمر الفرعي status حالة التشغيل والمقاييس النشطة
لأداة Memory Limiter:
adb shell am memory-limiter statusفي ما يلي مثال على الناتج:
Memory limiter
enabled monitoring=true ignored=none
visibleMem=1948MB visibleSwap=974MB
notVisibleMem=974MB notVisibleSwap=487MB
started=36 watched=36 watch-failed=0
events=0 processes=36 process-hwm=36
تشمل الحقول الرئيسية في الناتج ما يلي:
monitoring- يشير هذا إلى ما إذا كانت ميزة "الحدّ من استخدام الذاكرة" تراقب العمليات بشكل نشط.
visibleMemوnotVisibleMem- الحدود القصوى المطلقة للذاكرة (
memory.high) التي يتم فرضها حاليًا لكل حالة ظهور. visibleSwapوnotVisibleSwap- حدود التبديل المطلقة المحسوبة (
memory.swap.max) التي يتم فرضها حاليًا لكل حالة ظهور events- عدد المرات التي تجاوزت فيها عملية الحدّ المسموح به
processes- العدد الحالي للعمليات الخاضعة للمراقبة
تجاهل
يستبعد الأمر الفرعي ignore مؤقتًا معرّف مستخدم معيّن أو جميع العمليات
من تقييد الذاكرة. هذا مفيد لقياس الأداء أو اختبار الضغط أو تشخيص سلوك الذاكرة:
# Ignore a specific UID adb shell am memory-limiter ignore 10087# Ignore all processes (temporarily disables limiting) adb shell am memory-limiter ignore all# Resume normal limiting operation adb shell am memory-limiter ignore none
يدوي
يتجاوز الأمر الفرعي manual الحدود المحسوبة لعملية معيّنة
حسب معرّف العملية (PID) بقيمة مطلقة مخصّصة بالبايت. يجب أن تكون القيمة عددًا صحيحًا، ولكن يمكن أن تتضمّن اللاحقة MB للإشارة إلى ميبي بايت أو اللاحقة GB للإشارة إلى غيبي بايت:
# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1073741824# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1024MB# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1GB# Remove the manual override for PID 1234 adb shell am memory-limiter manual 1234 none
لا تسري عمليات الإلغاء اليدوية إلا على مدة تشغيل مثيل العملية المحدّد. إذا تمت إعادة تشغيل العملية، ستعود إلى الحدود العادية استنادًا إلى حالتها.
لا يمكن أن يتجاوز التجاوز اليدوي حدود النظام المادية.