اندروید ۱۷ و بالاتر از محدودکننده حافظه پشتیبانی میکند، که یک سرویس سیستمی است که با استفاده از لینوکس cgroup نسخه ۲، میزان استفاده از حافظه توسط فرآیندهای برنامه را نظارت و محدود میکند. محدودکننده حافظه مانع از مصرف بیش از حد حافظه سیستم توسط برنامههای خاص میشود، که فشار حافظه در کل سیستم را کاهش میدهد و از حذف تهاجمی فرآیندهای حیاتی با استفاده از پر کردن بیش از حد حافظه (OOM) جلوگیری میکند.
مکانیسم
محدودکننده حافظه با سرویس مدیریت فعالیت (AMS) ادغام میشود تا رویدادهای چرخه حیات فرآیند و تغییرات وضعیت را ردیابی کند. محدودکننده حافظه با استفاده از سیستم فایل cgroup v2 هسته لینوکس، محدودیتهای حافظه را اعمال میکند.
برای استفاده از محدودکننده حافظه، هسته دستگاه باید از cgroup v2 و کنترلکننده memory پشتیبانی کند. این سرویس به طور خاص به ویژگیهای زیر متکی است:
-
memory.high - یک محدودیت نرم. وقتی از آن عبور شود، فرآیند متوقف میشود و هسته تلاش میکند حافظه را از آن پس بگیرد.
-
memory.swap.max - میزان فضای swap که فرآیند میتواند استفاده کند را محدود میکند.
تأثیر بر برنامهها
برنامههایی که از محدودیت حافظه خود تجاوز نمیکنند، تحت تأثیر محدودکننده حافظه قرار نمیگیرند.
وقتی یک برنامه از حد مجاز memory.high خود عبور میکند، هسته حافظه فایل پشتیبان برنامه را حذف میکند و حافظه ناشناس آن را جابجا میکند تا برنامه در محدوده مجاز باقی بماند. در نتیجه حذف و تعویض، برنامه ممکن است کندتر اجرا شود.
در بدترین حالت، اگر برنامه به تخصیص حافظه ناشناس ادامه دهد و دستگاه فضای swap را تمام کند، ممکن است برنامه در تخصیص حافظه ناموفق باشد و در نتیجه احتمالاً از کار بیفتد.
نظارت بر فرآیند
محدودکننده حافظه به طور پیشفرض فرآیندهای برنامه (UID >= 10000) را رصد میکند. فرآیندهای سیستمی معمولاً برای کمک به تأیید پایداری سیستم اصلی، از این امر مستثنی هستند.
محدودکننده حافظه، محدودیتهای حافظه را بر اساس وضعیت فرآیند تعیین میکند:
فرآیندهای قابل مشاهده برای کاربر قابل درک هستند، مانند فعالیتهای پیشزمینه، سرویسهای پیشزمینه یا سایر حالتهای قابل درک توسط کاربر.
فرآیندهای غیرقابل مشاهده، فرآیندهای پسزمینهای هستند که با کاربر تعامل ندارند یا برای او قابل مشاهده نیستند.
جدول زیر حالتهای خاص فرآیند را به محدودیتهای حافظه نگاشت میکند:
| وضعیت فرآیند | محدودیت حافظه |
|---|---|
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) اجازه پردازشهای غیرقابل مشاهده را میداد.
تغییر پیکربندی
برای تغییر محدودیتهای سراسری سیستم، مراحل زیر را دنبال کنید:
-
/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
لغو دستی فقط در چرخه حیات فرآیند اعمال میشود. اگر فرآیند مجدداً راهاندازی شود، بر اساس وضعیت آن به محدودیتهای پیشفرض باز میگردد.