فرایند مخفی بستن برنامه‌ها ناشی از کمبود حافظه

فرایند مخفی (lmkd) که برنامه‌ها را به‌دلیل کمبود حافظه در Android می‌بندد، وضعیت حافظه سیستم Android درحال اجرا را پایش می‌کند و با بستن فرایندهای غیرضروری به فشار زیاد روی حافظه واکنش نشان می‌دهد تا عملکرد سیستم را در سطح قابل‌قبول حفظ کند.

درباره فشار حافظه

سیستم Android که چندین فرایند را به‌طور موازی اجرا می‌کند ممکن است با شرایطی مواجه شود که حافظه سیستم تمام شده باشد و فرایندهایی که به حافظه بیشتری نیاز دارند با تأخیرهای قابل‌توجهی مواجه شوند. فشار حافظه، وضعیتی که در آن سیستم با کمبود حافظه مواجه می‌شود، باعث می‌شود Android با محدود کردن یا بستن فرایندهای غیرمهم، درخواست از فرایندها برای آزاد کردن منابع غیرحیاتی ذخیره‌شده در حافظه نهان، و غیره، حافظه را آزاد کند (برای کاهش فشار).

در گذشته، Android فشار حافظه سیستم را بااستفاده از درایور «بستن ناشی از کمبود حافظه» (LMK) در هسته نظارت می‌کرد، مکانیزمی سخت که به مقادیر کدگذاری‌شده وابسته است. از هسته ۴.۱۲، درایور LMK از هسته بالادستی برداشته شده است و فضای کاربر lmkd وظایف نظارت بر حافظه و بستن فرایند را انجام می‌دهد.

اطلاعات توقف فشار

‫Android 10 و نسخه‌های بالاتر از حالت جدید lmkd پشتیبانی می‌کنند که از پایشگرهای اطلاعات توقف فشار هسته (PSI) برای تشخیص فشار حافظه استفاده می‌کند. مجموعه وصله PSI در هسته بالادستی (به هسته‌های ۴.۹ و ۴.۱۴ منتقل شده است) مدت زمانی را که تکالیف به‌دلیل کمبود حافظه به‌تأخیر می‌افتند اندازه‌گیری می‌کند. ازآنجایی‌که این تأخیرها مستقیماً بر تجربه کاربری تأثیر می‌گذارند، سنجه مناسبی برای تعیین شدت فشار روی حافظه هستند. هسته بالادستی همچنین شامل مانیتورهای PSI است که به فرایندهای فضای کاربری ممتاز (مانند lmkd) اجازه می‌دهد آستانه‌هایی را برای این تأخیرها مشخص کنند و درصورت نقض آستانه، در رویدادهای هسته مشترک شوند.

نظارت‌های PSI درمقابل سیگنال‌های vmpressure

چون سیگنال‌های vmpressure (که توسط هسته برای تشخیص فشار حافظه تولید می‌شود و توسط lmkd استفاده می‌شود) اغلب شامل موارد مثبت کاذب متعددی است، lmkd باید فیلتر کردن را انجام دهد تا مشخص کند آیا حافظه تحت فشار واقعی است یا نه. این امر منجر به lmkd بیدار شدن غیرضروری و استفاده از منابع محاسباتی اضافی می‌شود. استفاده از PSI باعث می‌شود فشار حافظه با دقت بیشتری تشخیص داده شود و سربار فیلتر کردن به حداقل برسد.

استفاده از پایشگرهای PSI

برای استفاده از مانیتورهای PSI به‌جای رویدادهای vmpressure، ویژگی ro.lmk.use_psi را پیکربندی کنید. پیش‌فرض true است، که باعث می‌شود پایشگرهای PSI سازوکار پیش‌فرض تشخیص فشار حافظه برای lmkd باشند. چون پایشگرهای PSI به پشتیبانی هسته نیاز دارند، هسته باید شامل وصله‌های backport PSI باشد و با فعال بودن پشتیبانی PSI (CONFIG_PSI=y) کامپایل شود.

معایب درایور LMK درون هسته

Android درایور LMK را به‌دلیل چند مشکل منسوخ می‌کند، ازجمله:

  • دستگاه‌های با حافظه دسترسی تصادفی کم باید به‌صورت تهاجمی تنظیم می‌شدند و حتی در این صورت نیز در حجم‌های کاری با صفحه فعال پشتیبان‌گیری‌شده با فایل بزرگ عملکرد ضعیفی داشتند. عملکرد ضعیف منجر به شکست و عدم کشتن شد.
  • درایور هسته LMK به محدودیت‌های حافظه آزاد متکی بود و هیچ مقیاس‌بندی‌ای براساس فشار حافظه نداشت.
  • به‌دلیل انعطاف‌ناپذیری طراحی، شرکا اغلب درایور را سفارشی‌سازی می‌کردند تا در دستگاه‌هایشان کار کند.
  • گرداننده LMK به میانای برنامه‌سازی کاربردی slab shrinker متصل شده بود که برای عملیات سنگین مانند جستجوی اهداف و ازبین بردن آن‌ها طراحی نشده بود و این امر فرایند vmscan را کند می‌کرد.

Userspace lmkd

lmkd فضای کاربر همان عملکرد درایور درون هسته را پیاده‌سازی می‌کند اما از سازوکارهای هسته موجود برای شناسایی و تخمین فشار حافظه استفاده می‌کند. چنین سازوکارهایی شامل استفاده از رویدادهای vmpressure تولیدشده توسط هسته یا پایشگرهای اطلاعات توقف تحت فشار (PSI) برای دریافت اعلان درباره سطوح فشار حافظه، و استفاده از ویژگی‌های گروه کنترل حافظه برای محدود کردن منابع حافظه اختصاص‌یافته به هر فرایند براساس اهمیت فرایند است.

استفاده از lmkd فضای کاربر در Android 10

در Android 9 و نسخه‌های بالاتر، اگر دراور LMK درون هسته شناسایی نشود، فضای کاربر lmkd فعال می‌شود. ازآنجایی‌که فضای کاربر lmkd به پشتیبانی هسته برای گروه‌های کنترل حافظه نیاز دارد، هسته باید با تنظیمات پیکربندی زیر کامپایل شود:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

استراتژی‌های کشتن

فضای کاربر lmkd از استراتژی‌های کشتن براساس رویدادهای vmpressure یا پایش‌های PSI، شدت آن‌ها، و نشان‌های دیگر مثل استفاده از مبادله پشتیبانی می‌کند. استراتژی‌های بستن برنامه‌ها در دستگاه‌های با حافظه کم و دستگاه‌های با عملکرد بالا متفاوت است:

  • در دستگاه‌های دارای حافظه کم، سیستم باید فشار حافظه بالاتر را به‌عنوان حالت عملکرد عادی تحمل کند.
  • در دستگاه‌های با عملکرد بالا، فشار حافظه باید به‌عنوان وضعیتی غیرعادی درنظر گرفته شود و قبل‌از اینکه بر عملکرد کلی تأثیر بگذارد، برطرف شود.

می‌توانید راهبرد کشتن را بااستفاده از دارایی ro.config.low_ram پیکربندی کنید.

فضای کاربر lmkd همچنین از حالت قدیمی‌ای پشتیبانی می‌کند که در آن تصمیمات کشتن را بااستفاده از همان استراتژی‌های درایور LMK درون هسته (یعنی آستانه‌های حافظه آزاد و حافظه نهان فایل) می‌گیرد. برای فعال کردن حالت قدیمی، خصوصیت ro.lmk.use_minfree_levels را روی true تنظیم کنید.

پیکربندی lmkd

lmkd را برای دستگاهی خاص بااستفاده از ویژگی‌های زیر پیکربندی کنید.

دارایی استفاده کردن پیش‌فرض
ro.config.low_ram مشخص کنید دستگاه دارای RAM کم است یا عملکرد بالایی دارد. false
ro.lmk.use_psi از پایشگرهای PSI (به‌جای رویدادهای vmpressure) استفاده کنید. true
ro.lmk.use_minfree_levels از آستانه‌های حافظه آزاد و حافظه نهان فایل برای تصمیم‌گیری درباره بستن فرایندها استفاده کنید (یعنی عملکرد درایور LMK درون هسته را مطابقت دهید). false
ro.lmk.low حداقل امتیاز oom_adj برای فرایندهای واجدشرایط برای بسته شدن در سطح پایین vmpressure. ‫1001
(غیرفعال)
ro.lmk.medium حداقل امتیاز oom_adj برای فرایندهای واجدشرایط برای متوقف شدن در سطح متوسط vmpressure. 800
(سرویس‌های حافظه نهان یا غیرضروری)
ro.lmk.critical حداقل امتیاز oom_adj برای فرایندهای واجدشرایط برای متوقف شدن در سطح بحرانی vmpressure. 0
(هر فرایندی)
ro.lmk.critical_upgrade ارتقا به سطح بحرانی را فعال کنید. false
ro.lmk.upgrade_pressure حداکثر mem_pressure که در آن سطح ارتقا می‌یابد زیرا سیستم بیش‌ازحد درحال جابه‌جایی است. ‫100
(غیرفعال)
ro.lmk.downgrade_pressure حداقل mem_pressure که در آن رویداد vmpressure نادیده گرفته می‌شود زیرا هنوز حافظه آزاد کافی دردسترس است. ‫100
(غیرفعال)
ro.lmk.kill_heaviest_task سنگین‌ترین تکلیف واجدشرایط را متوقف کن (بهترین تصمیم) درمقایسه با هر تکلیف واجدشرایط (تصمیم سریع). false
ro.lmk.kill_timeout_ms مدت‌زمان برحسب میلی‌ثانیه پس‌از توقف اجباری که در آن توقف اجباری دیگری انجام نخواهد شد. ‫0
(غیرفعال)
ro.lmk.debug گزارش‌های اشکال‌زدایی lmkd را فعال کنید. false

نمونه پیکربندی دستگاه:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.lmk.low=1001 \
    ro.lmk.medium=800 \
    ro.lmk.critical=0 \
    ro.lmk.critical_upgrade=false \
    ro.lmk.upgrade_pressure=100 \
    ro.lmk.downgrade_pressure=100 \
    ro.lmk.kill_heaviest_task=true

کاربرفضای lmkd در Android 11

‫Android 11 با معرفی استراتژی جدید کشتن، lmkd را بهبود می‌بخشد. استراتژی بستن از سازوکار PSI برای تشخیص فشار حافظه استفاده می‌کند که در Android 10 معرفی شده است. ‫lmkd در Android 11 سطوح استفاده از منبع حافظه و جابه‌جایی داده‌ها در حافظه را درنظر می‌گیرد تا از کمبود حافظه و افت عملکرد جلوگیری کند. این استراتژی کشتن جایگزین استراتژی‌های قبلی می‌شود و می‌تواند در هر دو دستگاه با عملکرد بالا و با حافظه دسترسی تصادفی پایین (Android Go) استفاده شود.

الزامات هسته

برای دستگاه‌های Android 11، lmkd به ویژگی‌های هسته زیر نیاز دارد:

  • وصله‌های PSI را اضافه کنید و PSI را فعال کنید (نسخه‌های قدیمی در هسته‌های مشترک Android 4.9،‏ 4.14، و 4.19 دردسترس است).
  • وصله‌های پشتیبانی PIDFD را اضافه کنید (پورت‌های پشتیبان در هسته‌های مشترک Android‏ ۴.۹، ۴.۱۴، و ۴.۱۹ دردسترس است).
  • برای دستگاه‌های با حافظه دسترسی تصادفی کم، cgroups حافظه را اضافه کنید.

هسته باید با تنظیمات پیکربندی زیر کامپایل شود:

CONFIG_PSI=y

پیکربندی lmkd در Android 11

استراتژی کشتن حافظه در Android 11 از پیچ‌های تنظیم و پیش‌فرض‌های فهرست‌شده در زیر پشتیبانی می‌کند. این ویژگی‌ها در دستگاه‌های با عملکرد بالا و حافظه دسترسی تصادفی پایین کار می‌کند.

دارایی استفاده کردن پیش‌فرض
عملکرد بالا حافظه دسترسی تصادفی کم
ro.lmk.psi_partial_stall_ms آستانه توقف جزئی PSI، برحسب میلی‌ثانیه، برای راه‌اندازی اعلان حافظه کم. اگر دستگاه اعلان‌های فشار حافظه را خیلی دیر دریافت می‌کند، این مقدار را کاهش دهید تا اعلان‌ها زودتر راه‌اندازی شوند. اگر اعلان‌های فشار حافظه به‌طور غیرضروری راه‌اندازی می‌شوند، این مقدار را افزایش دهید تا دستگاه به صدا حساسیت کمتری نشان دهد. 70 200
ro.lmk.psi_complete_stall_ms آستانه توقف کامل PSI، برحسب میلی‌ثانیه، برای راه‌اندازی اعلان‌های حافظه حیاتی. اگر دستگاه اعلان‌های فشار بحرانی حافظه را خیلی دیر دریافت می‌کند، این مقدار را کاهش دهید تا اعلان‌ها زودتر راه‌اندازی شوند. اگر اعلان‌های فشار حافظه بحرانی به‌طور غیرضروری راه‌اندازی می‌شوند، این مقدار را افزایش دهید تا دستگاه به نویز حساسیت کمتری نشان دهد. 700
ro.lmk.thrashing_limit حداکثر مقدار خطاهای کاری به‌عنوان درصدی از کل اندازه حافظه نهان صفحه پشتیبان فایل. اگر مقدار Workingset refaults بالاتر از این مقدار باشد، یعنی سیستم درحال کوبیدن حافظه پنهان صفحه است. اگر عملکرد دستگاه درطول فشار حافظه تحت‌تأثیر قرار می‌گیرد، مقدار را کاهش دهید تا تخریب محدود شود. اگر عملکرد دستگاه به‌دلیل دلیل غیرضروری برای کوبیدن متوقف شد، مقدار را افزایش دهید تا کوبیدن بیشتری مجاز شود. 100 30
ro.lmk.thrashing_limit_decay آستانه تخریب که به‌صورت درصد از آستانه اصلی بیان می‌شود برای کاهش آستانه زمانی استفاده می‌شود که سیستم حتی پس‌از کشتن نیز بهبود نمی‌یابد. اگر کوبش پیوسته باعث کشتارهای غیرضروری می‌شود، مقدار را کاهش دهید. اگر پاسخ به کوبش پیوسته پس‌از کشتن بسیار کند است، مقدار را افزایش دهید. 10 50
ro.lmk.swap_util_max حداکثر مقدار حافظه مبادله‌شده به‌صورت درصد از کل حافظه قابل‌مبادله. وقتی حافظه مبادله‌شده از این حد فراتر می‌رود، یعنی سیستم بیشتر حافظه قابل‌مبادله خود را مبادله کرده است و همچنان تحت فشار است. این وضعیت زمانی رخ می‌دهد که تخصیص‌های غیرقابل تعویض فشار حافظه ایجاد می‌کنند که با تعویض نمی‌توان آن را کاهش داد زیرا بیشتر حافظه قابل تعویض قبلاً تعویض شده است. مقدار پیش‌فرض ۱۰۰ است که عملاً این بررسی را غیرفعال می‌کند. اگر عملکرد دستگاه درطول فشار حافظه تحت‌تأثیر قرار می‌گیرد، درحالی‌که استفاده از فضای مبادله بالا است و سطح فضای مبادله آزاد به ro.lmk.swap_free_low_percentage کاهش نمی‌یابد، مقدار را کاهش دهید تا استفاده از فضای مبادله محدود شود. 100 100

دکمه‌های تنظیم قدیمی زیر نیز با استراتژی جدید توقف کار می‌کنند.

دارایی استفاده کردن پیش‌فرض
عملکرد بالا حافظه دسترسی تصادفی کم
ro.lmk.swap_free_low_percentage سطح مبادله آزاد به‌عنوان درصدی از کل فضای مبادله. `lmkd` از این مقدار به‌عنوان آستانه‌ای برای زمانی استفاده می‌کند که سیستم را به‌عنوان فضای مبادله گرسنه درنظر بگیرد. اگر `lmkd` درحالی‌که فضای زیادی در swap وجود دارد، درصد را کاهش دهید. اگر کشتن‌های `lmkd` خیلی دیر اتفاق می‌افتد و باعث می‌شود کشتن‌های OOM اتفاق بیفتد، درصد را افزایش دهید. 20 10
ro.lmk.debug با این کار، گزارش‌های اشکال‌زدایی `lmkd` فعال می‌شود. اشکال‌زدایی را درحین تنظیم فعال کنید. false