اندروید ۱۷ و بالاتر از Memory Limiter پشتیبانی میکند، که یک سرویس سیستمی است که با استفاده از Linux cgroup v2، میزان استفاده از حافظه توسط فرآیندهای برنامه را نظارت و محدود میکند. Memory Limiter از مصرف بیش از حد حافظه سیستم توسط برنامههای خاص جلوگیری میکند، که فشار حافظه در کل سیستم را کاهش میدهد و از حذف تهاجمی فرآیندهای حیاتی به دلیل کمبود حافظه (OOM) جلوگیری میکند.
مکانیسم
محدودکننده حافظه با سرویس مدیریت فعالیت (AMS) ادغام میشود تا رویدادهای چرخه حیات فرآیند و تغییرات وضعیت را ردیابی کند. محدودکننده حافظه با استفاده از سیستم فایل cgroup v2 هسته لینوکس، محدودیتهای حافظه را اعمال میکند.
برای استفاده از محدودکننده حافظه، هسته دستگاه باید از cgroup v2 و کنترلکننده memory پشتیبانی کند. این سرویس به طور خاص به ویژگیهای زیر متکی است:
-
memory.high - یک محدودیت نرم. وقتی از آن عبور شود، فرآیند متوقف میشود و هسته تلاش میکند حافظه را از آن پس بگیرد.
-
memory.swap.max - میزان فضای swap که فرآیند میتواند استفاده کند را محدود میکند.
تأثیر بر برنامهها
برنامههایی که از محدودیت حافظه خود تجاوز نمیکنند، تحت تأثیر محدودکننده حافظه قرار نمیگیرند.
وقتی یک برنامه از حد مجاز memory.high خود عبور میکند، هسته حافظه فایل پشتیبان برنامه را حذف میکند و حافظه ناشناس آن را جابجا میکند تا برنامه در محدوده مجاز باقی بماند. در نتیجه حذف و تعویض، برنامه ممکن است کندتر اجرا شود.
در بدترین حالت، اگر برنامه به تخصیص حافظه ناشناس ادامه دهد و دستگاه فضای swap را تمام کند، ممکن است برنامه در تخصیص حافظه ناموفق باشد و در نتیجه احتمالاً از کار بیفتد.
نظارت بر فرآیند
محدودکننده حافظه به طور پیشفرض فرآیندهای برنامه (UID >= 10000) را رصد میکند. فرآیندهای سیستمی معمولاً برای کمک به تأیید پایداری سیستم اصلی، از این امر مستثنی هستند.
محدودکننده حافظه، محدودیتهای حافظه را بر اساس وضعیت فرآیند تعیین میکند:
فرآیندهای قابل مشاهده در وضعیتی هستند که میتوانند رابط کاربری (UI) را به کاربر نشان دهند. هنگام نمایش رابط کاربری، انتظار میرود که یک فرآیند از مجموعه کاری RAM بیشتری استفاده کند، بنابراین محدودیت حافظه بیشتری برای آن فراهم میشود.
فرآیندهای نامرئی در وضعیتی هستند که به طور فعال کار انجام میدهند اما رابط کاربری را ترسیم نمیکنند. آنها برای انجام این کار از حافظه استفاده میکنند، اما کمتر از آنچه هنگام نمایش رابط کاربری نیاز دارند، بنابراین محدودیت بیشتری به آنها داده میشود.
جدول زیر حالتهای خاص فرآیند را به محدودیتهای حافظه نگاشت میکند:
| وضعیت فرآیند | محدودیت حافظه |
|---|---|
PERSISTENT | نامحدود |
PERSISTENT_UI | نامحدود |
TOP | قابل مشاهده |
BOUND_TOP | قابل مشاهده |
FOREGROUND_SERVICE | قابل مشاهده نیست |
BOUND_FOREGROUND_SERVICE | قابل مشاهده نیست |
IMPORTANT_FOREGROUND | قابل مشاهده |
IMPORTANT_BACKGROUND | قابل مشاهده نیست |
TRANSIENT_BACKGROUND | قابل مشاهده نیست |
BACKUP | قابل مشاهده نیست |
SERVICE | قابل مشاهده نیست |
RECEIVER | قابل مشاهده نیست |
TOP_SLEEPING | قابل مشاهده |
HEAVY_WEIGHT | قابل مشاهده نیست |
HOME | قابل مشاهده نیست |
LAST_ACTIVITY | قابل مشاهده نیست |
CACHED_ACTIVITY | ذخیره شده |
CACHED_ACTIVITY_CLIENT | ذخیره شده |
CACHED_RECENT | ذخیره شده |
CACHED_EMPTY | ذخیره شده |
در حالت ذخیره شده در حافظه پنهان، فرآیندها منجمد شده و سپس تا حد امکان بازیابی میشوند.
وقتی یک فرآیند از حد مجاز memory.high تعیینشده برای خود فراتر میرود، Memory Limiter این رویداد را تشخیص میدهد و میتواند اقدامات اشکالزدایی مانند ثبت یک پروفایل حافظه یا ثبت یک ناهنجاری در statsd را آغاز کند.
پیکربندی
محدودکننده حافظه را با استفاده از یک فایل XML که در پارتیشن vendor قرار دارد، پیکربندی کنید. پیکربندی به شما امکان میدهد محدودیتهای مطلق حافظه را بر اساس محدودیتهای خاص حافظه دستگاه تنظیم کنید.
مسیر فایل:
/vendor/etc/memory-limiter-config.xmlپیکربندی پیشفرض: اگر فایل پیکربندی پیدا نشود، یا اگر غیرقابل خواندن یا نامعتبر باشد، محدودکننده حافظه غیرفعال میشود.
فرمت 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 - یک عدد صحیح مثبت که نسخه پیکربندی را مشخص میکند. این عدد باید ۱ باشد.
-
minimumRequiredMemTotal - حداقل حافظه سیستم مورد نیاز برای معتبر بودن این محدودیت تعیین شده.
-
memVisible - محدودیت حافظه (
memory.high) امکان نمایش پردازشها را فراهم میکرد. -
memNotVisible - محدودیت حافظه (
memory.high) اجازه پردازشهای غیرقابل مشاهده را میداد. -
swapVisible - محدودیت swap (
memory.swap.max) اجازه پردازشهای قابل مشاهده را میداد. -
swapNotVisible - محدودیت swap (
memory.swap.max) اجازه پردازشهای غیرقابل مشاهده را میداد.
دستورالعملهای محدودیت حافظه دستگاه
هنگام تنظیم محدودیتهای حافظه برای دستگاه خود، دستورالعملهای زیر را در نظر بگیرید:
محدودیتهای متناسب با قابلیتهای سختافزاری: تولیدکنندگان اصلی دستگاه میتوانند محدودیتهایی را متناسب با قابلیتهای سختافزاری دستگاه خود تعیین کنند. اندروید محدودههای زیر را توصیه میکند:
- فرآیندهای قابل مشاهده: حداقل ۱/۲ و حداکثر ۲/۳ کل رم فیزیکی.
- فرآیندهای نامرئی: ۱/۴ تا ۱/۳ کل رم فیزیکی. تولیدکنندگان اصلی تجهیزات (OEM) میتوانند بر اساس قابلیتهای دستگاه و موارد استفاده، تصمیمات متفاوتی بگیرند.
نبود API زمان اجرا برای برنامهها: از اندروید ۱۷ (SDK 37)، برنامهها API برای پرسوجو در مورد محدودیتهای حافظه در زمان اجرا ندارند. تولیدکنندگان اصلی تجهیزات (OEM) باید این موضوع را در نظر بگیرند و از تعیین محدودیتهای خیلی پایین خودداری کنند و اطمینان حاصل کنند که برنامهها در موارد استفاده معقول به محدودیتها برخورد نمیکنند.
پیکربندی جهانی: این محدودیتها برای تمام فرآیندهای برنامه روی دستگاه، از جمله برنامههای از پیش نصب شده، اعمال میشود. هیچ لیست مجوزی برای معافیت برنامههای خاص از این محدودیتها وجود ندارد.
تغییر پیکربندی
برای تغییر محدودیتهای سراسری سیستم، مراحل زیر را دنبال کنید:
-
/vendor/etc/memory-limiter-config.xml را تغییر دهید. - برای اعمال تغییرات، دستگاه را مجدداً راه اندازی کنید یا
system_serverمجدداً راه اندازی کنید.
دستورات پوسته
دستور am memory-limiter به شما و توسعهدهندگان اجازه میدهد تا در زمان اجرا برای توسعه و آزمایش با سرویس تعامل داشته باشید:
am memory-limiter <SUB-COMMAND>وضعیت
زیردستور status وضعیت عملیاتی محدودکننده حافظه را گزارش میدهد:
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 ، محدودیتهای محاسبهشده برای یک فرآیند خاص (توسط شناسه فرآیند یا PID) را با یک مقدار مطلق سفارشی بر حسب مگابایت (MB) لغو میکند:
adb shell am memory-limiter manual 1234 1024 // Set a 1024 MB limit for PID 1234adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234
لغو دستی فقط در چرخه حیات فرآیند اعمال میشود. اگر فرآیند مجدداً راهاندازی شود، بر اساس وضعیت آن به محدودیتهای پیشفرض باز میگردد.