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(در MiB، شامل کف) موردنیاز برای اعمال این مجموعه محدودیت. این سرویس آن را درمقایسه با کل حافظه دردسترس گزارششده توسط هسته در/proc/meminfoارزیابی میکند.درک کردن بخشهای حافظه و مرزها: مقدار هسته
MemTotalنشاندهنده DRAM فیزیکی است که پساز کسر بخشهای حافظه سختافزار و میانافزار، سیستمعامل به آن دسترسی دارد. بخشهای مجزا RAM را برای اجزای سختافزاری تخصصی مانند واحد پردازش گرافیکی، مودم باند پایه، دوربین ISP، محیطهای اجرای امن، و ابرناظرها رزرو میکنند که معمولاً بین ۵۰۰ مگابایت و بیشاز ۲ گیگابایت حافظه فیزیکی مصرف میکنند.چون
MemTotalکمتر از DRAM فیزیکی تبلیغشده دستگاه است، آستانههایminimumRequiredMemTotalحاشیه این بخشهای جداشده را دربرمیگیرد. برای مثال، پیکربندی هدفیابی دستگاههای ۱۶ گیگابایتی کف14336(۱۴ گیگابایت) را بهجای16384(۱۶ گیگابایت) مشخص میکند، و سطح دستگاههای ۱۲ گیگابایتی کف9216(۹ گیگابایت) را مشخص میکند. این کار تضمین میکند که هر دستگاه، صرفنظر از تغییرات سطح برد، با سطح موردنظر خود مطابقت داشته باشد.maximumAllowedMemTotalحداکثر
MemTotalسیستم (در MiB، سقف انحصاری) برای اعمال این مجموعه محدودیت. اگرMemTotalبزرگتر از این سقف یا مساوی با آن باشد، محدوده تنظیمشده اعمال نمیشود. برای دستگاههای دارای ۱۸٬۴۳۲ مبیبایت یا بیشتر یا برای دستگاههای دارای کمتر از ۳٬۲۰۰ مبیبایت، «محدودکننده حافظه» محدودیتی اعمال نمیکند و فرایندها را بدون محدودیت رها میکند.memVisibleحد حافظه نرم (
memory.high) در مگابایت برای فرایندهای نمایان اعمال شد.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) |
محدودیت حافظه غیرقابلرؤیت (memNotVisible) |
محدودیت جابهجایی رؤیتپذیر (swapVisible) |
محدودیت مبادله غیرقابلرؤیت (swapNotVisible) |
|---|---|---|---|---|---|
| ۱۶ گیگابایت | [14336, 18432) مبیبایت |
۱۰۲۴۰ مگابایت (۱۰ گیگابایت) | ۵٬۱۲۰ مبیبایت (۵ گیبیبایت) | ۵٬۱۲۰ مگابایت (۵ گیگابایت) | ۵٬۱۲۰ مگابایت (۵ گیگابایت) |
| ۱۲ گیگابایت | [9216, 14336) مبیبایت |
۸٬۱۹۲ مبیبایت (۸ گیبیبایت) | ۴٬۰۹۶ مبیبایت (۴ گیبیبایت) | ۴٬۰۹۶ مبیبایت (۴ گیبیبایت) | ۴۰۹۶ مگابایت (۴ گیگابایت) |
| ۸ گیگابایت | [6800, 9216) مبیبایت |
۵٬۱۲۰ مگابایت (۵ گیگابایت) | ۳٬۰۷۲ مبیبایت (۳ گیبیبایت) | ۳۰۷۲ مگابایت (۳ گیگابایت) | ۳٬۰۷۲ مبیبایت (۳ گیبیبایت) |
| ۶ گیگابایت | [4800, 6800) مبیبایت |
۴۰۹۶ مگابایت (۴ گیگابایت) | ۲٬۰۴۸ مگابایت (۲ گیگابایت) | ۲٬۰۴۸ مگابایت (۲ گیگابایت) | ۲٬۰۴۸ مگابایت (۲ گیگابایت) |
| ۴ گیگابایت | [3200, 4800) مبیبایت |
۲٬۰۴۸ مگابایت (۲ گیگابایت) | ۱٬۰۲۴ مبیبایت (۱ گیبیبایت) | ۱٬۰۲۴ مگابایت (۱ گیگابایت) | ۱٬۰۲۴ مبیبایت (۱ گیبیبایت) |
اصول محدودیت حافظه
پیکربندی «محدودکننده حافظه» براساس اصول پلاتفرم زیر طراحی شده است:
سازگاری برنامه و یکپارچگی بومسازگان: محدودیتهای حافظه یکسان در دستگاهها عملکرد قابلپیشبینی برنامه را در سراسر بومسازگان Android تضمین میکند. برنامهها براساس انتظارات استاندارد حافظه توسعه و آزمایش میشوند؛ حفظ حدود یکنواخت پلاتفرم از محدودسازی غیرمنتظره یا پایانهای زودرس جلوگیری میکند.
تخصیص متناسب منابع: حدود پلاتفرم براساس ظرفیت فیزیکی RAM کالیبره میشود:
- فرایندهای نمایان: تقریباً ۱/۲ تا ۲/۳ از کل RAM فیزیکی برای پشتیبانی از بار کاریهای فعال میانای کاربری، ترکیب، و پردازش اختصاص داده شده است.
- فرایندهای نامرئی: تقریباً ۱/۴ تا ۱/۳ از کل RAM فیزیکی برای تکالیف پسزمینه اختصاص داده شده است.
کاربرد جهانی: محدودیتها بهطور یکنواخت بر همه فرایندهای برنامه در دستگاه (UID >= 10000)، ازجمله برنامههای سیستم ازپیش نصبشده و برنامههای سازنده تجهیزات اصلی اعمال میشود. «محدودکننده حافظه» از فهرستهای مجاز برای معاف کردن برنامههای خاص پشتیبانی نمیکند و از این طریق مدیریت منصفانه حافظه را در همه برنامهها تضمین میکند.
عدم وجود «میاناهای برنامهسازی کاربردی پُرسمان زمان اجرا»: در Android 17 و نسخههای بالاتر، برنامهها نمیتوانند بهصورت برنامهریزیشده محدودیتهای حافظه اختصاصدادهشده خود را در زمان اجرا پُرسمان کنند. محدودیتهای استاندارد پلاتفرم با حاشیههای سخاوتمندانه تعریف شدهاند تا برنامههای خوشرفتار درطول استفاده عادی بدون محدودیت عمل کنند.
پویاسازی مبادله و پسگیری هسته: وقتی فرایند برنامهای به
memory.highحد مجاز خود نزدیک میشود، هسته Linux پسگیری حافظه را بهطور خاص به آن گروه کنترل فرایند هدایت میکند. این شامل حذف کردن صفحههای غیرفعال با پشتیبان فایل و تبدیل کردن صفحههای ناشناس سرد به ZRAM میشود و بدون تحمیل فشار حافظه سراسری، سیالیت سیستم را حفظ میکند.
فرمانهای پوسته
دستور 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 بهطور موقت یک 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
لغوهای دستی فقط برای طول عمر آن نمونه فرایند خاص اعمال میشود. اگر فرایند بازراهاندازی شود، به محدودیتهای استاندارد براساس وضعیت خود بازمیگردد.
لغو دستی نمیتواند از محدودیتهای فیزیکی سیستم فراتر رود.