התהליך Android low memory killer daemon (lmkd
) עוקב אחרי מצב הזיכרון של מערכת Android שפועלת, ומגיב ללחץ זיכרון גבוה על ידי סגירת התהליכים הכי פחות חיוניים כדי לשמור על רמת ביצועים מקובלת במערכת.
מידע על לחץ על הזיכרון
במערכת Android שמפעילה כמה תהליכים במקביל, יכולות להיות מצבים שבהם זיכרון המערכת מתרוקן ותהליכים שדורשים יותר זיכרון נתקלים בעיכובים משמעותיים. לחץ על הזיכרון, מצב שבו המערכת משתמשת בזיכרון קצר, דורש שמערכת Android תפנה מקום בזיכרון (כדי להרגיע את הלחץ) על ידי ויסות נתונים (throttle) או הסרה של תהליכים לא חשובים, בקשת תהליכים לפינוי משאבים שאינם קריטיים במטמון וכן הלאה.
בעבר, מערכת Android ניהלה את לחץ הזיכרון של המערכת באמצעות מנהל התקן מובנה במוות זיכרון (LMK) – מנגנון נוקשה שתלוי בערכים שכתובים בתוך הקוד. החל מהליבה (kernel) 4.12, מנהל ה-LMK מוסר מהליבה (kernel) של ה-upstream, ומרחב המשתמשים lmkd
מבצע מעקב אחרי זיכרון והרג תהליכים.
מידע על עמדת הלחץ
ב-Android מגרסה 10 ואילך יש תמיכה במצב lmkd
חדש שמשתמש במעקב אחרי PSI (מידע על עצירה בלחץ הליבה) לזיהוי לחץ זיכרון. ערכת התיקונים של PSI בליבה של המקור (שעברה פורטרט לליבת 4.9 ולליבת 4.14) מודדת את משך הזמן שבו המשימות מתעכבות כתוצאה ממחסור בזיכרון. עיכובים כאלה משפיעים ישירות על חוויית המשתמש, ולכן הם מהווים מדד נוח לקביעת חומרת הלחץ על הזיכרון. הליבה של המקור כוללת גם מעקב PSI שמאפשר לתהליכים עם הרשאות של מרחב המשתמש (כמו lmkd
) לציין ערכי סף לעיכובים האלה ולהירשם לאירועים מהליבה כשמתרחש מעבר ערך הסף.
מעקב PSI לעומת אותות vmpressure
מכיוון שהאותות של vmpressure
(שנוצרים על ידי הליבה לצורך זיהוי לחץ בזיכרון ומשמשים את lmkd
) כוללים לעיתים קרובות הרבה תוצאות חיוביות שגויות, lmkd
צריך לבצע סינון כדי לקבוע אם יש לחץ אמיתי בזיכרון.
כתוצאה מכך, אין יותר צורך ב-lmkd
אירועי שינה ושימוש במשאבי חישוב נוספים. שימוש ב-PSI עוקב אחרי התוצאות לזיהוי מדויק יותר של לחץ הזיכרון ומצמצם את תקורת הסינון.
שימוש במוני PSI
כדי להשתמש במעקבי PSI במקום באירועי vmpressure
, צריך להגדיר את המאפיין ro.lmk.use_psi
. ברירת המחדל היא true
, כך ש-PSI monitors הוא המנגנון שמוגדר כברירת מחדל לזיהוי לחץ זיכרון ב-lmkd
. צגי PSI דורשים תמיכה בליבה (kernel), ולכן הליבה צריכה לכלול את תיקוני היציאה העורפית של PSI ולהיות הידור שלה עם תמיכה ב-PSI מופעלת (CONFIG_PSI=y
).
החסרונות של מנהל LMK בליבה
מערכת Android מפסיקה את השימוש ב-LMK driver בגלל מספר בעיות, כולל:
- במכשירים עם זיכרון RAM נמוך היה צריך לבצע התאמה אגרסיבית, וגם אז הביצועים היו נמוכים בעומסי עבודה עם pagecache פעיל גדול שמבוסס על קובץ. הביצועים הירודים הובילו לטרחה (thrashing) וללא הריגות.
- מנהל התקן הליבה של ה-LMK הסתמך על מגבלות הזיכרון החופשי, ללא התאמה לעומס (scaling) על סמך הלחץ על הזיכרון.
- בגלל הנוקשות של העיצוב, השותפים התאימו אישית את מנהל ההתקן כדי שיפעל במכשירים שלהם.
- מנהל ה-LMK מחובר ל-API של מכשיר הצמצום של הלוחות, שלא תוכנן לפעולות כבדות כמו חיפוש מטרות והפסקה שלהן, וכתוצאה מכך הוא האט את תהליך
vmscan
.
lmkd במרחב המשתמש
במרחב המשתמשים lmkd
יש את אותה הפונקציונליות כמו מנהל התקן הליבה, אבל נעשה שימוש במנגנוני ליבה קיימים כדי לזהות ולהעריך את הלחץ על הזיכרון. המנגנונים האלה כוללים שימוש באירועי vmpressure
שנוצרים בליבה או במעקב אחרי מידע על לחץ עצירה (PSI) כדי לקבל התראות על רמות הלחץ בזיכרון, ושימוש בתכונות של cgroup בזיכרון כדי להגביל את משאבי הזיכרון שמוקצים לכל תהליך על סמך מידת החשיבות שלו.
שימוש במרחב המשתמשים (lmkd) ב-Android 10
ב-Android 9 ואילך, מרחב המשתמש lmkd
מופעל אם לא מזוהה מנהל LMK בליבה. מאחר שמרחב המשתמש lmkd
מחייב תמיכה בליבה ב-cgroups של זיכרון, צריך לבצע הידור של הליבה עם הגדרות התצורה הבאות:
CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
אסטרטגיות להפסקת פעילות
Userspace lmkd
תומך באסטרטגיות הפסקה על סמך אירועי vmpressure
או מעקב PSI, החומרה שלהם והצעות אחרות כמו ניצול של swap. אסטרטגיות ההוצאה משימוש שונות במכשירים עם זיכרון נמוך ובמכשירים עם ביצועים גבוהים:
- במכשירים עם נפח זיכרון נמוך, המערכת אמורה לסבול עומס גבוה יותר על הזיכרון כמצב עבודה רגיל.
- במכשירים עם ביצועים גבוהים, צריך להתייחס לעומס על הזיכרון כמצב חריג ולתקן אותו לפני שהוא משפיע על הביצועים הכוללים.
אפשר להגדיר את אסטרטגיית המחיקה באמצעות המאפיין ro.config.low_ram
. פרטים נוספים זמינים במאמר הגדרה של נפח זיכרון RAM נמוך.
Userspace 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 מביאים בחשבון את רמות השימוש במשאבי הזיכרון ואת הטרישה (thrashing) כדי למנוע מצב של מחסור בזיכרון ופגיעה בביצועים.
אסטרטגיית ההגנה הזו מחליפה אסטרטגיות קודמות, ואפשר להשתמש בה גם במכשירים עם ביצועים גבוהים וגם במכשירים עם RAM נמוך (Android Go).
דרישות הליבה
במכשירי Android 11, lmkd
מחייב את תכונות הליבה הבאות:
- צריך לכלול תיקוני PSI ולהפעיל PSI (יציאות לאחור זמינות בליבות נפוצות של Android בגרסאות 4.9, 4.14 ו-4.19).
- כולל תיקוני תמיכה ב-PIDFD (גרסאות backport זמינות בליבות הנפוצות של Android בגרסאות 4.9, 4.14 ו-4.19).
- במכשירים עם זיכרון RAM נמוך, צריך לכלול קבוצות cgroup של זיכרון.
צריך להדר את הליבה עם הגדרות התצורה הבאות:
CONFIG_PSI=y
הגדרת lmkd ב-Android 11
שיטת 'השמדת זיכרון' ב-Android 11 תומכת בלחצני הבקרה ובברירת המחדל שמפורטים בהמשך. אפשר להשתמש בתכונות האלה גם במכשירים עם ביצועים גבוהים וגם במכשירים עם זיכרון RAM נמוך.
נכס | שימוש | ברירת מחדל | |
---|---|---|---|
ביצועים גבוהים | נפח RAM נמוך | ||
ro.lmk.psi_partial_stall_ms |
הסף לסטול חלקי של PSI, במילישניות, להפעלת התראה על זיכרון נמוך. אם המכשיר מקבל התראות על לחץ על הזיכרון מאוחר מדי, צריך להקטין את הערך הזה כדי להפעיל התראות מוקדמות יותר. אם ההתראות על לחץ בזיכרון מופעלות ללא צורך, כדאי להגדיל את הערך הזה כדי שהמכשיר יהיה פחות רגיש לרעש. | 70 |
200 |
ro.lmk.psi_complete_stall_ms |
סף העיכוב המלא של PSI, במילישניות, להפעלת התראות על מצב זיכרון קריטי. אם המכשיר מקבל התראות על לחץ זיכרון קריטי מאוחר מדי, אפשר להקטין את הערך הזה כדי להפעיל התראות מוקדם יותר. אם ההתראות על לחץ זיכרון קריטי מופעלות ללא צורך, כדאי להגדיל את הערך הזה כדי שהמכשיר יהיה פחות רגיש לרעש. | 700 |
|
ro.lmk.thrashing_limit |
מספר הבקשות המקסימלי להחזרת ערכים שמוגדרים כברירת מחדל בקבוצת עבודה, כאחוז מהגודל הכולל של מטמון הדפים שמבוסס על קבצים. כשמספר הטעויות של Workingset חורג מהערך הזה, המערכת נחשבת כמייצרת עומס יתר על pagecache. אם הביצועים של המכשיר מושפעים במהלך לחץ זיכרון, צריך להקטין את הערך כדי להגביל את הטרישה. אם הביצועים של המכשיר נפגעים ללא צורך בגלל טרחה, צריך להגדיל את הערך כדי לאפשר יותר טרחה. | 100 |
30 |
ro.lmk.thrashing_limit_decay |
הירידה של ערך הסף לטרחה, שמתבטאת כאחוז מערך הסף המקורי, שמשמשת להקטנת הסף כשהמערכת לא מתאוששת גם אחרי הפסקה. אם טרישה מתמשכת יוצרת הפסקות מיותרות, צריך להקטין את הערך. אם התגובה לטרחה רציפה אחרי 'kill' איטית מדי, צריך להגדיל את הערך. | 10 |
50 |
ro.lmk.swap_util_max |
הכמות המקסימלית של הזיכרון המוחלף כאחוז מתוך סך הזיכרון שניתן להחלפה. אם נפח הזיכרון שעבר החלפה חורג מהמגבלה הזו, המשמעות היא שהמערכת החליפה את רוב הזיכרון שאפשר להחליף, והיא עדיין בלחץ.
המצב הזה יכול לקרות כשהקצאות שלא ניתן להחליף יוצרות לחץ על הזיכרון, ולא ניתן להקל עליו באמצעות החלפה כי רוב הזיכרון שאפשר להחליף כבר הוחלף. ערך ברירת המחדל הוא 100, ולכן למעשה
משבית את הבדיקה הזו. אם הביצועים של המכשיר מושפעים במהלך לחץ זיכרון בזמן שהשימוש בזיכרון החלופי גבוה ורמת הזיכרון החלופי הפנוי לא יורדת ל-ro.lmk.swap_free_low_percentage , צריך להקטין את הערך כדי להגביל את השימוש בזיכרון החלופי. |
100 |
100 |
הלחצנים הישנים הבאים לכוונון פועלים גם עם אסטרטגיית ההוצאה משימוש החדשה.
נכס | שימוש | ברירת מחדל | |
---|---|---|---|
ביצועים גבוהים | זיכרון RAM נמוך | ||
ro.lmk.swap_free_low_percentage |
רמת ההחלפה החופשית כאחוז מתוך שטח ההחלפה הכולל. הערך הזה משמש את lmkd כסף גבול לקביעת המצב שבו המערכת נמצאת במחסור במרחב שמנוצל להחלפה. אם 'lmkd' הורג בזמן שיש יותר מדי מקום בזיכרון החלופי, צריך להקטין את האחוז. אם הריצות מסוג 'lmkd' מתרחשות מאוחר מדי, ומאפשרות הרוגות ל-OOM להתרחש, ומגדילים את האחוז. | 20 |
10 |
ro.lmk.debug |
הפעולה הזו מפעילה את יומני ניפוי הבאגים של lmkd. מפעילים את ניפוי הבאגים בזמן ההתאמה. | false |