يتضمّن الإصدار 17 من نظام التشغيل Android والإصدارات الأحدث خدمة Memory Limiter، وهي خدمة تابعة للنظام تراقب استخدام الذاكرة في عمليات التطبيقات وتضع قيودًا عليه باستخدام الإصدار 2 من مجموعة التحكّم في Linux. يمنع Memory Limiter التطبيقات الفردية من استهلاك كمية غير متناسبة من ذاكرة النظام، ما يقلّل من الضغط العام على الذاكرة ويمنع عمليات الإنهاء القسري للعمليات المهمة في المقدّمة والعمليات المخزّنة مؤقتًا عند انخفاض الذاكرة.
آلية العمل
يتكامل Memory Limiter مع خدمة "مدير الأنشطة" (AMS) لتتبُّع أحداث دورة حياة العمليات وتغييرات الحالة. يفرض Memory Limiter حدود الذاكرة باستخدام التسلسل الهرمي cgroup v2 لنواة Linux.
لكي يتوافق الجهاز مع أداة "تحديد سقف استخدام الذاكرة"، يجب أن يفعّل نواة الجهاز الإصدار 2 من cgroup وأداة التحكّم memory. تعتمد الخدمة تحديدًا على السمات التالية:
memory.high- حدّ أقصى مرن وعند تجاوز هذا الحد، يتم تقييد العملية ويحاول النواة استرداد الصفحة بشكل استباقي من تلك العملية.
memory.swap.max- يحدّد الحد الأقصى لمقدار مساحة التبديل (مثل ZRAM) التي يمكن للعملية استخدامها.
التأثير على التطبيقات
لا يتأثر التطبيقات التي تعمل ضمن حدود الذاكرة المسموح بها بأداة Memory Limiter.
عندما يتجاوز التطبيق حد memory.high، تعمل النواة على إخلاء ذاكرة التطبيق النظيفة المستندة إلى الملفات واستبدال الذاكرة المجهولة غير النشطة للحفاظ على التطبيق ضمن الحد. نتيجةً لعملية إخلاء الصفحة واستبدالها، قد يواجه التطبيق تقييدًا مؤقتًا في التنفيذ، ولكنّه سيستمر في العمل.
في الحالات القصوى، مثل حدوث تسرّب الذاكرة غير المتحكَّم فيه يستمر فيه التطبيق في تخصيص ذاكرة مجهولة الهوية بعد استنفاد مساحة الإبدال، يتعذّر على التطبيق تخصيص الذاكرة ويتم إنهاؤه.
مراقبة العمليات
يراقب "أداة تحديد سقف استخدام الذاكرة" عمليات التطبيقات (UID >= 10000) تلقائيًا. ويتم استثناء عمليات النظام الأساسية للحفاظ على استقرار النظام.
يحدّد Memory Limiter حدود الذاكرة استنادًا إلى حالة ظهور العملية:
العمليات المرئية: العمليات التي تستضيف واجهة مستخدم مرئية (مثل النشاط الذي يتم التركيز عليه حاليًا أو التفاعل النشط). وبما أنّ عرض واجهة مستخدم يتطلّب مجموعة عمل أكبر لعمليات العرض وخطوط أنابيب الرسومات، فإنّ العمليات المرئية تتلقّى حدًا أكثر سخاءً للذاكرة.
العمليات غير المرئية: العمليات التي تنفّذ مهامًا في الخلفية بدون عرض واجهة مستخدم (مثل الخدمات التي تعمل في الخلفية أو أدوات استقبال البث). وبما أنّها لا تعرض عناصر واجهة المستخدم، فإنّها تعمل ضمن حدّ أكثر صرامة.
يوضّح الجدول التالي كيفية ربط حالات العمليات المحدّدة بتصنيفات حد الذاكرة:
| حالة العملية | حد الذاكرة |
|---|---|
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، يرصد أداة Memory Limiter الحدث ويمكنه بدء إجراءات تشخيصية، مثل تسجيل ملف ذاكرة أو تسجيل خلل في statsd.
الإعداد
في الإصدار 17 من نظام التشغيل Android والإصدارات الأحدث، يتم ضبط أداة Memory Limiter باستخدام ملف إعداد النظام الأساسي العادي في قسم النظام على /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) الخاص بالكاميرا وبيئات التنفيذ الآمنة وبرامج Hypervisor، وعادةً ما تستهلك ما بين 500 ميغابايت وأكثر من 2 غيغابايت من الذاكرة الفعلية.بما أنّ قيمة
MemTotalأقل من ذاكرة الوصول العشوائي الديناميكية (DRAM) الفعلية المُعلن عنها للجهاز، تتضمّن حدودminimumRequiredMemTotalالدنيا هامشًا لهذه المساحات المخصّصة. على سبيل المثال، يحدّد الإعداد الذي يستهدف الأجهزة بسعة 16 غيغابايت حدًا أدنى يبلغ14336(14 غيغابايت) بدلاً من16384(16 غيغابايت)، ويحدّد مستوى الأجهزة بسعة 12 غيغابايت حدًا أدنى يبلغ9216(9 غيغابايت). ويضمن ذلك أن يتوافق كل جهاز مع الفئة المقصودة بغض النظر عن الاختلافات في التصميم على مستوى اللوحة.maximumAllowedMemTotalتمثّل هذه السمة الحد الأقصى لنظام
MemTotal(بوحدة MiB، الحد الأعلى غير شامل) الذي يجب أن ينطبق على مجموعة الحدود هذه. إذا كانMemTotalأكبر من أو يساوي هذا الحد الأقصى، لن يسري الحدّ الذي تم ضبطه. بالنسبة إلى الأجهزة التي تبلغ سعتها 18,432 مبيبايت أو أكثر أو الأجهزة التي تقل سعتها عن 3,200 مبيبايت، لا يفرض Memory Limiter أي قيود، ما يترك العمليات بدون قيود.memVisibleالحد الأقصى المبدئي للذاكرة (
memory.high) بوحدة MiB الذي يتم تطبيقه على العمليات المرئيةmemNotVisibleالحدّ الأقصى المبدئي للذاكرة (
memory.high) بوحدة قياس "ميغابايت" الذي يتم تطبيقه على العمليات غير المرئيةswapVisibleالحد الأقصى لمساحة التبديل (
memory.swap.max) بوحدة MiB المطبّق على العمليات المرئيةswapNotVisibleالحد الأقصى لمساحة التبديل (
memory.swap.max) بوحدة MiB المطبّق على العمليات غير المرئية
الحدود القصوى العادية للمنصة
في الإصدار 17 من نظام التشغيل Android والإصدارات الأحدث، تحدّد المنصة حدودًا عادية للذاكرة ومساحة التبديل في /system/etc/memory-limiter-config.xml عبر فئات ذاكرة الوصول العشوائي (RAM) الشائعة باستخدام فواصل النطاق [floor, ceiling):
| استهداف ذاكرة الوصول العشوائي المادية |
نطاق MemTotal [floor, ceiling) (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) الفعلية إلى ثلثَيها لدعم أحمال العمل النشطة الخاصة بواجهة المستخدم والتركيب والعرض.
- العمليات غير المرئية: يتم تخصيص ما يقرب من ربع إلى ثلث إجمالي ذاكرة الوصول العشوائي (RAM) الفعلية للمهام التي تعمل في الخلفية.
إمكانية التطبيق على نطاق واسع: تنطبق الحدود بشكل موحّد على جميع عمليات التطبيقات على الجهاز (معرّف المستخدم >= 10000)، بما في ذلك تطبيقات النظام والتطبيقات المثبّتة مسبقًا من الشركة المصنّعة للجهاز. لا يتيح تطبيق "محدد الذاكرة" قوائم السماح لاستثناء تطبيقات معيّنة، ما يضمن إدارة الذاكرة بشكل عادل في جميع التطبيقات.
عدم توفّر واجهات برمجة تطبيقات طلب البحث في وقت التشغيل: في نظام التشغيل Android 17 والإصدارات الأحدث، لا يمكن للتطبيقات طلب البحث آليًا عن حدود الذاكرة المخصّصة لها في وقت التشغيل. تم تحديد حدود المنصة العادية بهوامش كبيرة كي تعمل التطبيقات التي تتوافق مع السياسات بدون قيود أثناء الاستخدام العادي.
ديناميكيات استرداد الذاكرة وتبديلها في النواة: عندما تقترب عملية أحد التطبيقات من الحدّ الأقصى
memory.high، توجّه نواة Linux عملية استرداد الذاكرة إلى مجموعة التحكّم (cgroup) الخاصة بهذه العملية. ويشمل ذلك تجاهل الصفحات غير النشطة التي يتم تخزينها في ملفات، ونقل الصفحات المجهولة غير النشطة إلى 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 مؤقتًا معرّف مستخدم (UID) محدّدًا أو جميع العمليات من الحد الأقصى للذاكرة. ويكون ذلك مفيدًا عند وضع معايير للأداء أو إجراء اختبارات التحمّل أو تشخيص سلوك الذاكرة:
# 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 للإشارة إلى MiB أو اللاحقة GB للإشارة إلى GiB:
# 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
لا تسري عمليات الإلغاء اليدوية إلا طوال مدة مثيل العملية المحدّد. إذا تمت إعادة تشغيل العملية، ستعود إلى الحدود العادية استنادًا إلى حالتها.
لا يمكن أن يتجاوز التعديل اليدوي حدود النظام المادية.