Android 17 و نسخههای بالاتر شامل «محدودکننده حافظه» است، یک سرویس سیستم که بااستفاده از Linux cgroup v2، میزان استفاده از حافظه را در فرایندهای برنامه نظارت و محدود میکند. «محدودکننده حافظه» از مصرف نامتناسب حافظه سیستم توسط برنامههای مجزا جلوگیری میکند، که این امر فشار کلی روی حافظه را کاهش میدهد و از بستن تهاجمی فرایندهای مهم پیشزمینه و ذخیرهشده در حافظه نهان بهدلیل کمبود حافظه جلوگیری میکند.
سازوکار
«محدودکننده حافظه» با «سرویس مدیر فعالیت» (AMS) ادغام میشود تا رویدادهای چرخه حیات پردازش و تغییرات وضعیت را ردیابی کند. «محدودکننده حافظه» محدودیتهای حافظه را بااستفاده از سلسلهمراتب cgroup v2 هسته Linux اعمال میکند.
برای پشتیبانی از «محدودکننده حافظه»، هسته دستگاه باید cgroup v2 و کنترلکننده memory را فعال کند. این سرویس بهطور خاص به مشخصههای زیر متکی است:
memory.high- محدودیت نرم. وقتی از این حد فراتر رود، فرایند محدود میشود و هسته تلاش میکند صفحه را بهطور پیشگیرانه از آن فرایند پس بگیرد.
memory.swap.max- حداکثر مقدار فضای مبادله (مانند ZRAM) را که فرایند میتواند استفاده کند محدود میکند.
تأثیر بر برنامهها
برنامههایی که در محدوده حافظه خود کار میکنند تحت تأثیر «محدودکننده حافظه» قرار نمیگیرند.
وقتی برنامهای از حد memory.high خود فراتر میرود، هسته حافظه تمیز با پشتیبانی فایل برنامه را تخلیه میکند و حافظه ناشناس غیرفعال آن را جابهجا میکند تا برنامه را در حد مجاز نگه دارد. درنتیجه این فعالیت تخلیه و تعویض صفحه، ممکن است برنامه بهطور موقت با کاهش سرعت اجرا مواجه شود، اما همچنان به کار خود ادامه میدهد.
در شرایط حاد (مثلاً نشت حافظه کنترلنشده که در آن برنامه پساز اتمام فضای مبادله همچنان به اختصاص دادن حافظه ناشناس ادامه میدهد)، برنامه نمیتواند حافظه اختصاص دهد و متوقف میشود.
پایش فرایند
«محدودکننده حافظه» بهطور پیشفرض بر فرایندهای برنامه (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 اختصاصدادهشده به آن فراتر میرود، «محدودکننده حافظه»
رویداد را شناسایی میکند و میتواند کنشهای تشخیصی را راهاندازی کند، مثلاً ثبت کردن
نمایه حافظه یا ثبت کردن ناهنجاری در statsd.
پیکربندی
در Android 17 و نسخههای بالاتر، «محدودکننده حافظه» بااستفاده از فایل پیکربندی استاندارد پلاتفرم در پارتیشن سیستم در
/system/etc/memory-limiter-config.xml پیکربندی میشود.
فرمت XML
فایل پیکربندی از طرح تعریفشده در
memory-limiter-config.xsd پیروی میکند. این فایل چندین مجموعه محدودیت را تعریف میکند که براساس حافظه دردسترس مرتب شدهاند؛
سرویس بالاترین مجموعه محدودیت منطبق را براساس RAM دردسترس دستگاه انتخاب میکند. همه مقادیر حافظه برحسب مبیبایت (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 دوربین، محیطهای اجرای امن، و ناظران ماشین مجازی رزرو میکنند و معمولاً بین ۵۰۰ مبیبایت و بیشاز ۲ گیبیبایت از حافظه فیزیکی را مصرف میکنند.چون
MemTotalکمتر از DRAM فیزیکی تبلیغشده دستگاه است، آستانههایminimumRequiredMemTotalشامل حاشیهای برای این بخشهای جداشده است. برای مثال، پیکربندیای که دستگاههای ۱۶ گیگابایتی را هدف قرار میدهد، بهجای16384(۱۶ گیگابایت)، حداقل14336(۱۴ گیگابایت) را مشخص میکند، و ردهای برای دستگاههای ۱۲ گیگابایتی حداقل9216(۹ گیگابایت) را مشخص میکند. این کار تضمین میکند که هر دستگاه با سطح موردنظر خود مطابقت داشته باشد، صرفنظر از تغییرات استثنایی در سطح برد.maximumAllowedMemTotalحداکثر
MemTotalسیستم (به مبیبایت، سقف انحصاری) برای این حد تنظیم شده است تا اعمال شود. اگرMemTotalبزرگتر یا مساوی این سقف باشد، محدودیت تنظیمشده اعمال نمیشود. برای دستگاههای دارای ۱۸٬۴۳۲ مبیبایت یا بیشتر یا برای دستگاههای دارای کمتر از ۳٬۲۰۰ مبیبایت، «محدودکننده حافظه» محدودیتی اعمال نمیکند و فرایندها را بدون محدودیت رها میکند.memVisibleمحدودیت حافظه نرم (
memory.high) در MiB برای فرایندهای قابلمشاهده اعمال شد.memNotVisibleحد نرم حافظه (
memory.high) در MiB برای فرایندهای غیرقابلمشاهده اعمال شد.swapVisibleحد فضای مبادله (
memory.swap.max) در MiB برای فرایندهای نمایان اعمال شد.swapNotVisibleحد فضای مبادله (
memory.swap.max) در MiB برای فرایندهای غیرقابلمشاهده اعمال شد.
حدود استاندارد پلاتفرم
در Android 17 و نسخههای بالاتر، پلتفرم محدودیتهای استاندارد حافظه و مبادله را در /system/etc/memory-limiter-config.xml در سراسر ردیفهای رایج RAM فیزیکی بااستفاده از فاصلههای محدوده [floor, ceiling) مشخص میکند:
| حافظه دسترسی تصادفی فیزیکی هدف |
محدوده MemTotal [کف، سقف) (minimumRequiredMemTotal, maximumAllowedMemTotal) |
حد حافظه قابلمشاهده (memVisible) |
Not visible memory limit (memNotVisible) |
Visible swap limit (swapVisible) |
Not visible swap limit (swapNotVisible) |
|---|---|---|---|---|---|
| ۱۶ گیگابایت | [14336, 18432) مبیبایت |
۱۰٬۲۴۰ مبیبایت (۱۰ گیبیبایت) | ۵٬۱۲۰ مبیبایت (۵ گیبیبایت) | ۵٬۱۲۰ مبیبایت (۵ گیبیبایت) | ۵٬۱۲۰ مبیبایت (۵ گیبیبایت) |
| ۱۲ گیگابایت | [9216, 14336) مبیبایت |
۸٬۱۹۲ مبیبایت (۸ گیبیبایت) | ۴٬۰۹۶ مبیبایت (۴ گیبیبایت) | ۴٬۰۹۶ مبیبایت (۴ گیبیبایت) | ۴٬۰۹۶ مبیبایت (۴ گیبیبایت) |
| ۸ گیگابایت | [6800, 9216) مبیبایت |
۵٬۱۲۰ مبیبایت (۵ گیبیبایت) | ۳٬۰۷۲ مبیبایت (۳ گیبیبایت) | ۳٬۰۷۲ مبیبایت (۳ گیبیبایت) | ۳٬۰۷۲ مبیبایت (۳ گیبیبایت) |
| ۶ گیگابایت | [4800, 6800) مبیبایت |
۴٬۰۹۶ مبیبایت (۴ گیبیبایت) | ۲٬۰۴۸ مبیبایت (۲ گیبیبایت) | ۲٬۰۴۸ مبیبایت (۲ گیبیبایت) | ۲٬۰۴۸ مبیبایت (۲ گیبیبایت) |
| ۴ گیگابایت | [3200, 4800) مبیبایت |
۲٬۰۴۸ مبیبایت (۲ گیبیبایت) | ۱٬۰۲۴ مبیبایت (۱ گیبیبایت) | ۱٬۰۲۴ مبیبایت (۱ گیبیبایت) | ۱٬۰۲۴ مبیبایت (۱ گیبیبایت) |
اصول محدودیت حافظه
پیکربندی «محدودکننده حافظه» براساس اصول پلاتفرم زیر طراحی شده است:
سازگاری بومسازگان و سازگاری برنامه: محدودیتهای حافظه یکسان در دستگاههای مختلف باعث میشود عملکرد برنامه در سراسر بومسازگان Android قابلپیشبینی باشد. برنامهها براساس انتظارات استاندارد حافظه توسعه داده میشوند و آزمایش میشوند؛ حفظ محدودیتهای یکنواخت پلتفرم از محدودسازی غیرمنتظره یا توقفهای زودهنگام جلوگیری میکند.
تخصیص متناسب منابع: محدودیتهای پلاتفرم براساس ظرفیت فیزیکی RAM کالیبره میشوند:
- فرایندهای نمایان: تقریباً ۱/۲ تا ۲/۳ از کل RAM فیزیکی را برای پشتیبانی از رابط کاربری فعال، ترکیببندی، و بارهای کاری پردازشی اختصاص میدهد.
- فرایندهای غیرقابلمشاهده: تقریباً ۱/۴ تا ۱/۳ از کل RAM فیزیکی برای کارهای پسزمینه اختصاص داده شده است.
قابلیت اعمال جهانی: محدودیتها بهطور یکسان بر همه فرایندهای برنامه در دستگاه (UID >= 10000)، ازجمله برنامههای سیستم و OEM ازپیش نصبشده، اعمال میشود. «محدودکننده حافظه» از فهرستهای مجاز برای مستثنی کردن برنامههای خاص پشتیبانی نمیکند تا از مدیریت عادلانه حافظه در همه برنامهها اطمینان حاصل شود. برای پیکربندی کفهای محافظتی خودتنظیم
memory.minدر دیمونهای تعاملی حیاتی و سقفهای کالیبرهشده با حجم کاریmemory.highسختگیرانهتر در برنامهها و سرویسهای سیستم بهصورت جداگانه، بودجههای حافظه سیستم را ببینید.نبود میاناهای برنامهسازی کاربردی پُرسمان زمان اجرا: در Android 17 و بالاتر، برنامهها نمیتوانند بهصورت برنامهنویسیشده محدودیتهای حافظه اختصاصدادهشده خود را در زمان اجرا پُرسمان کنند. حدود استاندارد پلاتفرم با حاشیههای سخاوتمندانه تعریف شدهاند تا برنامههای خوشرفتار درطول استفاده عادی بدون محدودیت عمل کنند.
پویاییهای بازیابی و مبادله هسته: وقتی فرایند برنامه به حد
memory.highخود نزدیک میشود، هسته Linux بازیابی حافظه را بهطور خاص به cgroup آن فرایند هدایت میکند. این شامل رها کردن صفحههای غیرفعال با پشتیبانی فایل و مبادله صفحههای ناشناس سرد به ZRAM، حفظ سیالیت سیستم بدون تحمیل فشار حافظه جهانی است.
فرمانهای Shell
فرمان 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 - محدودیتهای حافظه مطلق محاسبهشده (
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
لغو دستی فقط برای طول عمر آن نمونه فرایند خاص اعمال میشود. اگر فرایند بازراهاندازی شود، براساس وضعیتش به محدودیتهای استاندارد برمیگردد.
لغو دستی نمیتواند از محدودیتهای فیزیکی سیستم فراتر رود.