این صفحه تعامل بین kswapd و lmkd را در Android پوشش میدهد،
و نشان میدهد که چگونه آنها باهم کار میکنند تا فشار حافظه را مدیریت کنند.
پسزمینه
Android از دو سازوکار اصلی برای بازیابی حافظه درصورت کمبود حافظه سیستم استفاده میکند:
kswapd: یک دیمون هسته استاندارد Linux که با بیرون کردن صفحههای تمیز با پشتیبانی فایل یا جابهجا کردن صفحههای ناشناس به ZRAM، صفحهها را بازیابی میکند.lmkd: دیمن Low Memory Killer فضای کاربر Android. وقتیkswapdنمیتواند با درخواستهای حافظه همگام شود و فشار سیستم افزایش مییابد (همانطور که توسط PSI نشان داده میشود)،lmkdوارد عمل میشود تا فرایندها را متوقف کند و بخشهای بزرگتری از حافظه را آزاد کند.
kswapd و lmkd دو سیستم مکمل برای بازیابی حافظه هستند. آنها برای
رسیدن به یک هدف (ایجاد حافظه آزاد) اما با روشهای مختلف کار میکنند. برای مقایسه
و همسنجی:
- قابلبازیابی درمقابل مخرب:
kswapdصفحههای حافظه را که میتوانند از فضای ذخیرهسازی بازخوانی شوند رها میکند، یا صفحههای حافظه را به پارتیشنهای حافظه دیگر یا فضای ذخیرهسازی که میتواند درصورت درخواست بازخوانی شود جابهجا میکند.lmkdپردازشها را متوقف میکند، که وضعیت غیرفرار را ازبین میبرد. - پهنای باند بازیابی:
kswapdنسبتبهlmkdواحد پردازش مرکزی بیشتری برای بازیابی مقدار مشخصی از حافظه آزاد صرف میکند و بازیابی حافظه مذکور بیشتر طول میکشد.lmkdمیتواند مقدار زیادی از حافظه را در مدت کوتاهی با تلاش نسبتاً کمی بازیابی کند. درنظر داشته باشید که در دستگاههای همراه، تلاش CPU نه تنها به تأخیر، بلکه به مصرف باتری نیز ترجمه میشود.
باکتهای امتیاز کمبود حافظه
Android براساس اهمیت فرایندها برای کاربر، تنظیم امتیاز «کمبود حافظه» (OOM) (oom_score_adj) را به آنها اختصاص میدهد. پردازشهای با امتیاز بالاتر
زودتر متوقف میشوند.
دستههای رایج عبارتاند از:
- ذخیرهشده در حافظه نهان (امتیاز >= ۹۰۰): پردازشهایی که درحالحاضر نیاز نیستند و برای بازراهاندازی سریعتر نگهداری میشوند.
- سرویس (امتیاز ۵۰۰): پردازشهای میزبانی سرویسهای شروعشده.
- سرویس پیشزمینهای (امتیاز ۲۰۰): پردازشهای میزبان سرویسهای پیشزمینهای.
- پیشزمینه (امتیاز ۰): برنامهای که کاربر درحالحاضر با آن تعامل دارد.
ژرفکاوی: راهاندازی PSI و LMKD
PSI چیست؟
اطلاعات توقف فشار (PSI) یکی از ویژگیهای هسته Linux است که روشی استاندارد برای اندازهگیری کمبود منابع ارائه میدهد. این معیار زمان تأخیر تکالیف را بهدلیل کمبود CPU، حافظه، و I/O ردیابی میکند.
PSI حافظه: «برخی» درمقابل «کامل»
شاخص PSI حافظه بهطور خاص تأخیرهای ناشی از کمبود حافظه را ردیابی میکند (مثلاً انتظار برای بازیابی صفحه یا خطاهای مجدد). این بخش دو سنجه ارائه میدهد:
some: درصد زمانی که طی آن حداقل یک تکلیف بهدلیل حافظه متوقف شده است. این نشان میدهد که کمبود حافظه بر عملکرد تأثیر میگذارد اما برخیاز کارها همچنان درحال پیشرفت است.full: درصد زمانی که طی آن همه تکالیف غیربیکار بهطور همزمان متوقف شدهاند. این نشاندهنده وضعیت بحرانی است که در آن سیستم کاملاً مسدود شده و منتظر حافظه است.
نحوه راهاندازی LMKD توسط PSI
پسزمینه lmkd فضای کاربر در هسته ثبت میشود تا وقتی از آستانههای PSI فراتر رفت (با نظارت بر /proc/pressure/memory)، اعلان دریافت کند. وقتی سیستم فشار حافظه بالایی را تجربه میکند (مثلاً توقف full از مدت پیکربندیشده فراتر میرود)، هسته lmkd را بیدار میکند. سپس lmkd وضعیت سیستم را ارزیابی میکند و براساس امتیاز کمبود حافظه و اندازه فرایندها تصمیم میگیرد که کدام فرایندها را متوقف کند.
تنظیم LMKD
رفتار LMKD را میتوان بااستفاده از ویژگیهای سیستم تنظیم کرد.
یافتن مقادیر تنظیم در دستگاه
با اجرای دستور زیر میتوانید مقادیر تنظیم فعلی LMKD را در دستگاه متصل پیدا کنید:
adb shell getprop | grep lmk
ویژگیهای رایج LMKD
در اینجا برخیاز ویژگیهای کلیدی مورداستفاده برای تنظیم LMKD آورده شده است (برای فهرست کامل به اسناد Android مراجعه کنید):
-
ro.lmk.use_psi: رویtrueتنظیم کنید تا از نمایشگرهای PSI برای تشخیص فشار حافظه استفاده شود (بهطور پیشفرض در Android نسخه ۱۰ و بالاتر). ro.lmk.psi_partial_stall_ms: آستانه مدت توقف (جزئی)someبرحسب میلیثانیه برای راهاندازی توقف اجباری (بهطور پیشفرض ۷۰ میلیثانیه در دستگاههای معمولی، ۲۰۰ میلیثانیه در دستگاههای با حافظه دسترسی تصادفی کم).ro.lmk.psi_complete_stall_ms: آستانه مدت توقفfullبرحسب میلیثانیه برای راهاندازی توقف اجباری (پیشفرض ۷۰۰ میلیثانیه).-
ro.lmk.kill_heaviest_task: اگرtrue، LMKD فرایندی را که بیشترین حافظه را در بین نامزدها در همان سطل OOM استفاده میکند ازبین میبرد.
مقادیر تنظیم مربوطه در دستگاه آزمایشی (Google Pixel 8 Pro)
(توجه: پیشفرضهای معمول برای دستگاههای پیشرفته دارای Android 15)
ro.lmk.use_psi:truero.lmk.psi_partial_stall_ms:70(معمول)ro.lmk.psi_complete_stall_ms:700(معمول)ro.lmk.kill_heaviest_task:true
درستیسنجی ZRAM و swap
ظرفیت ZRAM تأثیر زیادی بر سرعت پر شدن فضای مبادله و فعال شدن توقفهای LMKD دارد. بااستفاده از این فرمانها میتوانید وضعیت ZRAM و swap را در دستگاه بررسی کنید:
# Check ZRAM sizing and usage
adb shell free -m
# Check swap partition details
adb shell cat /proc/swaps
تمرین عملی: راهاندازی kswapd و lmkd
در این تمرین، از برنامه نمونه KswapdLmkdLab برای ایجاد کردن
فرایندها در دستههای مختلف «کمبود حافظه» استفاده خواهید کرد و سپس حافظه را در فرایند اصلی
مصرف خواهید کرد تا kswapd و lmkd را راهاندازی کنید.
برنامه بهگونهای پیکربندی شده است که بهطور خودکار زیرفرایند ایجاد کند و حافظه را به آنها اختصاص دهد تا به اهداف جذابی برای LMKD تبدیل شوند.
۱. ایجاد زیرفرایندها
برنامه بهطور خودکار زیرفرایندهای زیر را هنگام راهاندازی ایجاد میکند:
- فرایند ذخیرهشده در حافظه نهان (oom_score_adj >= 900)
- فرایند سرویس (oom_score_adj 500)
- فرایند سرویس پیشزمینهای (oom_score_adj 200)
فرایندها و امتیازهای OOM آنها را بااستفاده از ADB درستیسنجی کنید:
adb shell dumpsys activity processes | grep com.android.kswapdlmkdlab
نمونه تکهکد خروجی:
Proc # 0: fg T/A/TOP LCMNFUATI t: 0 18959:com.android.kswapdlmkdlab/u0a358 (top-activity)
Proc # 1: prcp b/ /FGS -------TI t: 0 19050:com.android.kswapdlmkdlab:foreground/u0a358 (fg-service)
Proc # 2: svc b/ /SVC -------TI t: 0 19077:com.android.kswapdlmkdlab:service/u0a358 (started-services)
Proc # 3: cch b/ /CACC -------TI t: 0 19014:com.android.kswapdlmkdlab:cached/u0a358 (cch-client-act)
اختصارهای وضعیت فرایند مربوط به موارد زیر است:
-
fg: پیشزمینه (امتیاز OOM ۰) prcp: قابلدرک (سرویس پیشزمینهای، امتیاز کمبود حافظه ۲۰۰)-
svc: سرویس شروعشده (امتیاز OOM ۵۰۰) cch: پردازش ذخیرهشده در حافظه نهان (امتیاز OOM ۹۰۰)
۲. راهاندازی فشار حافظه
برنامه بهطور خودکار شروع به اختصاص حافظه در فرایند اصلی میکند. برای اینکه آزمایش در دستگاههای دارای RAM بالا مؤثر باشد، برنامه به زیرفرایندها نیز دستور میدهد حافظه اختصاص دهند (مثلاً هرکدام ۵۰۰ مگابایت) تا هدفهای بهتری برای LMKD باشند.
نظارت بر مرگ زیرپردازش
برنامه بااستفاده از سازوکار IBinder.linkToDeath بر مرگ این زیرفرایندها نظارت میکند:
- فرایند اصلی بااستفاده از
bindServiceبه سرویسی در فرایند هدف متصل میشود. - پساز اتصال، شیء
IBinderرا که نشاندهنده سرویس است دریافت میکند. - این روش با فراخوانی
linkToDeathدر binder، پیادهسازیIBinder.DeathRecipientرا ثبت میکند. - وقتی فرایند هدف ازبین میرود (برای مثال، وقتی توسط LMKD ازبین میرود)، سیستم
روش
binderDied()را فراخوانی میکند و به برنامه اجازه میدهد رویداد ازبین رفتن را بهصورت ناهمگام ثبت کند.
برای جلوگیری از اینکه این اتصال اولویت فرایندهای هدف را بالا ببرد
(که هدف تمرین را ازبین میبرد)، برنامه از پرچم
Context.BIND_WAIVE_PRIORITY استفاده میکند.
برنامه نمونه در عمل
در اینجا نماگرفتی از برنامه پساز تکمیل اجرای آزمایشی در Google Pixel 8 Pro (که درمجموع حدود ۱۲ گیگابایت حافظه دسترسی تصادفی دارد) ارائه شده است.
تحلیل ردیابی Perfetto
برای ضبط تعامل، از پیکربندی Perfetto زیر برای ضبط زمانبندی، شمارندههای حافظه، توقفهای LMK، و اطلاعات توقف فشار (PSI) استفاده کنید.
پیکربندی Perfetto
تعامل را با اجرای Perfetto با زمانبندی، شمارندههای حافظه، کشتنهای LMK، و اطلاعات توقف فشار (PSI) ضبط کنید:
adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/kswapd_lmkd.perfetto-trace <<EOF
buffers: { size_kb: 131072 }
data_sources: {
config {
name: "linux.ftrace"
ftrace_config {
ftrace_events: "lowmemorykiller/lowmemory_kill"
ftrace_events: "vmscan/mm_vmscan_kswapd_wake"
ftrace_events: "vmscan/mm_vmscan_kswapd_sleep"
ftrace_events: "psi/psi_event"
}
}
}
duration_ms: 180000
EOF
ردپا را مرور کنید
نماگرفت زیر از ردیابیای گرفته شده است که دوره زمانی
کمی قبلاز توقف فرایند :cached (با بیشترین احتمال توقف) تا
توقف فرایند :foreground (با کمترین احتمال توقف) را نشان میدهد.
میتوانید ببینید که MemFree درحالحاضر نسبتاً پایین است و تحت فشار مداوم قرار دارد.
kswapd بهطور مداوم درحال کار است و با حذف کردن صفحههای mem.rss.file و انتقال mem.rss.anon به mem.swap از همه پردازشهای kswapdlmkdlab (پردازش اصلی و پردازشهای فرعی) و احتمالاً از پردازشهای دیگری که در این نماگرفت نشان داده نشدهاند، فشار را کاهش میدهد. همزمان، برنامه kswapdlmkdlab
به اختصاص حافظه ادامه میدهد و فشار را سریعتر از آنچه kswapd بتواند
بازیابی کند افزایش میدهد.
وقتی فشار خیلی زیاد میشود، همانطور که در بالا بودن psi.mem برای مدت زمان کافی دیده میشود، lmkd بیدار میشود و برخیاز فرایندها را متوقف میکند. میتوانید ببینید که lmkd به امتیازهای OOM احترام میگذارد و ابتدا kswapdlmkdlab:cached، سپس :service، و بعد :foreground را میکشد.
خط زمان رویدادها را مرور کنید و درباره موارد زیر فکر کنید:
- چگونه
kswapdوlmkdمکمل یکدیگر هستند:kswapdاولین موردی است که به فشار حافظه پاسخ میدهد، اماlmkdزمانی کمک میکند که پهنای باند بازیابیkswapdتقاضای تخصیص را برآورده نمیکند. - نرخ آزاد شدن حافظه: زمان واحد پردازش مرکزی صرفشده در
kswapdو حافظه بازیابیشده با حذفmem.rss.fileیا جابهجاییmem.rss.anonبهmem.swapرا مشاهده کنید. این را با فورانهای کوتاه فعالیت درlmkdمقایسه کنید که منجر به آزاد شدن مقادیر زیادی از حافظه خصوصی پردازش میشود.
عبارتهای جستجو
این پُرسمانها را در میانای کاربر Perfetto (پُرسمان SQL) اجرا کنید تا دادهها را از ردگیریتان استخراج کنید.
۱. فعالیت kswapd
برای پیدا کردن زمان فعال بودن و اجرای دیمون مبادله هسته، این دستور را اجرا کنید:
SELECT ts, dur, state
FROM thread_state
JOIN thread USING (utid)
WHERE thread.name LIKE 'kswapd%'
AND state = 'Running'
LIMIT 5;
خروجی نمونه:
| ts | dur | ایالت |
|---|---|---|
| 30317633052969 | 159180 | درحال اجرا |
| 30317633398347 | 3999186 | درحال اجرا |
| 30317638448111 | 1847941 | درحال اجرا |
| 30317641455354 | 1031006 | درحال اجرا |
| 30317643272615 | 888387 | درحال اجرا |
۲. کشتههای LMKD
LMKD بستنهای ناشی از کمبود حافظه را در جدول instant مینویسد. برای پرسمان کردن همه کشتنهای LMKD:
SELECT ts, name
FROM instant
WHERE name LIKE 'lmk,%'
ORDER BY ts ASC;
قالب نام رویداد بهصورت زیر است:
lmk,<pid>,<kill_reason>,<oom_score_adj>,<min_oom_score>,<max_thrashing>.
kill_reason: عدد صحیحی که نشان میدهد چراlmkdتصمیم گرفت فرایند را متوقف کند (تعریفشده درsystem/memory/lmkd/statslog.h):0:PRESSURE_AFTER_KILL1:NOT_RESPONDING2:LOW_SWAP_AND_THRASHING(فضای مبادله ZRAM بسیار کم است و کوبش رخ داده است)3:LOW_MEM_AND_SWAP(حافظه آزاد و فضای مبادله ZRAM سیستم کم است)4:LOW_MEM_AND_THRASHING5:DIRECT_RECL_AND_THRASHING6:LOW_MEM_AND_SWAP_UTIL7:LOW_FILECACHE_AFTER_THRASHING8:LOW_MEM9:DIRECT_RECL_STUCK
max_thrashing: حداکثر درصد کوبش صفحه در زمان توقف اجباری.
خروجی نمونه:
| ts | نام |
|---|---|
| 30326148679967 | lmk,2308,3,900,201,0 |
| 30330439763710 | lmk,2309,3,500,201,0 |
| 30334985999837 | lmk,2310,2,200,0,307 |
دیداریسازی
برای تجسم دادهها، میتوانید از اسکریپت gnuplot زیر برای رسم حافظه آزاد سیستم، فعالیت kswapd، کشتنهای lmkd، و PSI در یک سری زمانی واحد استفاده کنید. فرض بر این است که اسکریپت از دایرکتوری بالای ساخت Android اجرا میشود.
نمونه نمودار برونداد
نمودار زیر بااستفاده از اسکریپت قبلی با دادههای نمونه معرف اجرای آزمایشی تولید شده است.
توضیح طرح داستان:
این نمودار تعامل پویا بین مؤلفههای مختلف مدیریت حافظه را درطول آزمون تنش نشان میدهد:
- کاهش حافظه آزاد: با اختصاص حافظه توسط برنامه اصلی، حافظه آزاد سیستم (خط بنفش) بهطور پیوسته کاهش مییابد.
- فعالسازی kswapd: وقتی حافظه آزاد به زیر حد مشخصی میرسد،
kswapdبیدار میشود (پالسهای آبی) تا با جابهجایی به ZRAM حافظه را بازیابی کند. این بهصورت جهشهای متناوب قابلمشاهده است. - جهشهای PSI: وقتی
kswapdبرای همگام شدن با نرخ بالای تخصیص تلاش میکند، رشتهها در تخصیص حافظه دچار وقفه میشوند و این امر باعث جهش PSI (اطلاعات وقفه فشار) (خط سبز) میشود. - LMKD Kills: وقتی PSI به سطوح بحرانی میرسد (مثلاً، از آستانه
ro.lmk.psi_complete_stall_msفراتر میرود) و حافظه آزاد بسیار کم است،lmkdبا ازبین بردن فرایندهای با اولویت پایین (تکانههای نارنجی در زمان ۳۰ و ۴۵) مداخله میکند تا بخشهای بزرگی از حافظه را آزاد کند. توجه داشته باشید که بلافاصله پساز توقف اجباری، حافظه آزاد افزایش مییابد و PSI کاهش مییابد، که نشاندهنده اثربخشی توقف اجباری در کاهش فشار است. ________________________________________________________________________________
← بازپسگیری حافظه: اخراج و مبادله | ↑ بالا | برگرداندن صفحههای حافظه به سیستمعامل →