این صفحه تعامل بین kswapd و lmkd را در Android پوشش میدهد،
و نشان میدهد که چگونه آنها باهم کار میکنند تا فشار حافظه را مدیریت کنند.
پسزمینه
Android از دو سازوکار اصلی برای بازیابی حافظه درصورت کمبود حافظه سیستم استفاده میکند:
kswapd: یک دیمون هسته استاندارد Linux که با بیرون کردن صفحههای تمیز با پشتیبانی فایل یا جابهجا کردن صفحههای ناشناس به ZRAM، صفحهها را بازیابی میکند.lmkd: شبح Low Memory Killer فضای کاربر Android. وقتیkswapdنمیتواند با تقاضای حافظه همگام شود و فشار سیستم افزایش مییابد (همانطور که توسط PSI نشان داده میشود)،lmkdوارد عمل میشود تا فرایندها را متوقف کند تا بخشهای بزرگتری از حافظه را آزاد کند.
kswapd و lmkd دو سیستم مکمل برای بازیابی حافظه هستند. هر دو برای رسیدن به یک هدف (ایجاد حافظه آزاد) اما با روشهای متفاوت کار میکنند. برای مقایسه
و همسنجی:
- قابلبازیابی درمقابل مخرب:
kswapdصفحههای حافظهای را که میتوانند از فضای ذخیرهسازی بازخوانی شوند رها میکند، یا صفحههای حافظه را به پارتیشنهای حافظه دیگر یا فضای ذخیرهسازی که میتواند درصورت درخواست بازخوانی شود جابهجا میکند.lmkdپردازشها را متوقف میکند، که وضعیت غیرفرار را ازبین میبرد. - Reclaim Bandwidth:
kswapdspends more CPU to reclaim a given amount of free memory thanlmkd, and takes longer to reclaim said memory.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 فرایندی را که بیشترین حافظه را در میان نامزدها در همان سطل کمبود حافظه استفاده میکند ازبین میبرد.
مقادیر تنظیم مربوطه در دستگاه آزمایشی (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: پیشزمینه (امتیاز کمبود حافظه ۰) prcp: قابلدرک (سرویس پیشزمینهای، امتیاز کمبود حافظه ۲۰۰)-
svc: سرویس شروعشده (امتیاز OOM ۵۰۰) cch: پردازش ذخیرهشده در حافظه نهان (امتیاز کمبود حافظه ۹۰۰)
۲. فشار حافظه راهانداز
برنامه بهطور خودکار شروع به اختصاص حافظه در فرایند اصلی میکند. برای اینکه آزمایش در دستگاههای دارای 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: وقتی PSI به سطوح بحرانی میرسد (مثلاً، از آستانه
ro.lmk.psi_complete_stall_msبهطور مفهومی فراتر میرود) و حافظه آزاد بسیار کم است،lmkdبا کشتن فرایندهای با اولویت پایین (تکانههای نارنجی در زمان ۳۰ و ۴۵) مداخله میکند تا بخشهای بزرگی از حافظه را آزاد کند. توجه داشته باشید که بلافاصله پساز توقف، حافظه آزاد افزایش مییابد و PSI کاهش مییابد، که نشاندهنده اثربخشی توقف در کاهش فشار است. ________________________________________________________________________________
← بازیابی حافظه: اخراج و مبادله | ↑ بالا | برگرداندن صفحههای حافظه به سیستمعامل →