يتوافق الإصدار 17 من نظام التشغيل Android والإصدارات الأحدث مع خدمة Memory Limiter، وهي خدمة تابعة لنظام التشغيل تراقب وتحدّ من استخدام الذاكرة في عمليات التطبيقات باستخدام الإصدار 2 من cgroup في Linux. يمنع Memory Limiter التطبيقات الفردية من استهلاك ذاكرة النظام بشكل مفرط، ما يقلّل من الضغط على الذاكرة على مستوى النظام ويمنع إيقاف العمليات المهمة بشكل مفرط بسبب نقص الذاكرة (OOM).
آلية العمل
يتكامل أداة Memory Limiter مع خدمة Activity Manager Service (AMS) لتتبُّع أحداث دورة حياة العمليات وتغييرات الحالة. يفرض Memory Limiter حدود الذاكرة باستخدام نظام ملفات cgroup v2 في نواة Linux.
لاستخدام أداة "تحديد سقف استخدام الذاكرة"، يجب أن يتيح نظام تشغيل الجهاز cgroup v2 ووحدة التحكّم
memory. تعتمد الخدمة تحديدًا على السمات التالية:
memory.high- حدّ أقصى مرن وعند تجاوز هذا الحد، يتم تقييد العملية ويحاول النواة استرداد الذاكرة منها.
memory.swap.max- يحدّ من مقدار مساحة التبديل التي يمكن أن تستخدمها العملية.
التأثير على التطبيقات
لا تتأثر التطبيقات التي لا تتجاوز حدود الذاكرة بميزة "محدد الذاكرة".
عندما يتجاوز تطبيق الحدّ 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.
الإعداد
اضبط Memory Limiter باستخدام ملف XML موجود على القسم vendor. تتيح لك إعدادات الضبط تعديل حدود الذاكرة المطلقة استنادًا إلى قيود الذاكرة المحدّدة للجهاز.
مسار الملف:
/vendor/etc/memory-limiter-config.xmlالإعداد التلقائي: إذا لم يتم العثور على ملف الإعداد أو إذا كان غير قابل للقراءة أو غير صالح، سيتم إيقاف أداة Memory Limiter.
تنسيق XML
يتّبع ملف الإعداد المخطط المحدّد في
memory-limiter-config.xsd. يتيح لك الملف تحديد مجموعات حدود متعددة، وتختار الخدمة المجموعة الأنسب استنادًا إلى ذاكرة الوصول العشوائي المتاحة على الجهاز. يتم تحديد جميع قيم الذاكرة بوحدات الميبيبايت (MiB).
<MemoryLimiterConfig>
<version>1</version>
<configList>
<limitSet>
<!-- Limits for a phone with at least 14G of ram: 8G/4G/4G/4G -->
<minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- عدد صحيح موجب يحدّد إصدار الإعداد. يجب أن تكون القيمة 1.
minimumRequiredMemTotal- الحد الأدنى المطلوب من ذاكرة النظام المتاحة لكي تكون مجموعة الحدود هذه صالحة
memVisible- الحد الأقصى للذاكرة (
memory.high) المسموح به للعمليات المرئية memNotVisible- الحدّ الأقصى للذاكرة (
memory.high) المسموح به للعمليات غير المرئية swapVisible- الحد الأقصى لمساحة التبديل (
memory.swap.max) المسموح بها للعمليات المرئية swapNotVisible- حدّ المبادلة (
memory.swap.max) المسموح به للعمليات غير المرئية
إرشادات الحد الأقصى لذاكرة الجهاز
عند ضبط حدود الذاكرة لجهازك، يُرجى مراعاة الإرشادات التالية:
تخصيص الحدود حسب إمكانات الجهاز: يمكن لمصنّعي الأجهزة الأصليين ضبط حدود مخصّصة حسب إمكانات أجهزتهم. يقترح نظام التشغيل Android النطاقات التالية:
- العمليات المرئية: يجب أن تشغل هذه العمليات ما لا يقل عن نصف إجمالي ذاكرة الوصول العشوائي (RAM) الفعلية وما لا يزيد عن ثلثَيها.
- العمليات غير المرئية: من ربع إلى ثلث إجمالي ذاكرة الوصول العشوائي الفعلية يمكن لمصنّعي المعدات الأصلية اتّخاذ قرارات مختلفة استنادًا إلى إمكانات الجهاز وحالات الاستخدام.
عدم توفّر واجهة برمجة تطبيقات لوقت التشغيل للتطبيقات: اعتبارًا من Android 17 (الإصدار 37 من حزمة تطوير البرامج)، لا تتضمّن التطبيقات واجهة برمجة تطبيقات للاستعلام عن حدود الذاكرة في وقت التشغيل. على الشركات المصنّعة للأجهزة الأصلية مراعاة ذلك وتجنُّب وضع حدود منخفضة جدًا، مع ضمان عدم تجاوز التطبيقات لهذه الحدود خلال حالات الاستخدام المعقولة.
الإعدادات العامة: تنطبق الحدود على جميع عمليات التطبيقات على الجهاز، بما في ذلك التطبيقات المثبَّتة مسبقًا. ولا تتوفّر قائمة مسموح بها لإعفاء بعض التطبيقات من هذه الحدود.
تعديل الإعدادات
لتغيير الحدود على مستوى النظام، اتّبِع الخطوات التالية:
- تعديل
/vendor/etc/memory-limiter-config.xml - أعِد تشغيل الجهاز أو أعِد تشغيل
system_serverلتفعيل التغييرات.
أوامر 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- حدِّد حدود الذاكرة المطلقة المحسوبة لكل حالة.
events- عدد المرات التي تجاوزت فيها إحدى العمليات الحدّ الأقصى المسموح به.
processes- عدد العمليات التي تتم مراقبتها
تجاهل
يستبعد الأمر الفرعي ignore مؤقتًا معرّف UID أو جميع العمليات من أن تكون
محدودة. ويكون هذا الإجراء مفيدًا لاختبار الأداء أو عند السماح لتطبيق معيّن بتجاوز حدوده.
adb shell am memory-limiter ignore 10087 // Ignore a specific UIDadb shell am memory-limiter ignore all // Ignore all processes (effectively disables limiting)adb shell am memory-limiter ignore none // Resume normal operation
يدوي
يلغي الأمر الفرعي manual الحدود المحسوبة لعملية معيّنة
(حسب معرّف العملية) بقيمة مطلقة مخصّصة بالبايت. يجب أن تكون القيمة عددًا صحيحًا، ولكن يمكن أن تتضمّن اللاحقة "MB" للإشارة إلى ميغابايت أو اللاحقة "GB" للإشارة إلى غيغابايت:
adb shell am memory-limiter manual 1234 1073741824 // Set a 1GiB limit for PID 1234adb shell am memory-limiter manual 1234 1024MB // Set a 1GiB limit for PID 1234adb shell am memory-limiter manual 1234 1GB // Set a 1GiB limit for PID 1234adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234
لا تنطبق عمليات التجاوز اليدوية إلا على دورة حياة العملية. إذا تمت إعادة تشغيل العملية، ستعود إلى الحدود التلقائية استنادًا إلى حالتها.
لا يمكن أن يتجاوز التعديل اليدوي أي حدود حالية للنظام.