התהליך של הדימון (daemon) של Android low memory killer (lmkd
) עוקב אחרי מצב הזיכרון של מערכת Android שפועלת, ומגיב לעומס גבוה על הזיכרון על ידי סגירת התהליכים הכי פחות חיוניים כדי לשמור על רמת ביצועים מקובלת של המערכת.
מידע על עומס זיכרון
במערכת Android שבה פועלים כמה תהליכים במקביל, יכולים להיות מצבים שבהם הזיכרון של המערכת מוצה, ותהליכים שדורשים יותר זיכרון יחוו עיכובים משמעותיים. עומס על הזיכרון הוא מצב שבו הזיכרון של המערכת עומד להיגמר. כדי להקל על העומס, מערכת Android צריכה לפנות זיכרון על ידי הגבלת תהליכים לא חשובים או סיום שלהם, שליחת בקשות לתהליכים לפנות משאבים לא קריטיים שנשמרו במטמון וכו'.
בעבר, מערכת Android ניהלה מעקב אחרי העומס על זיכרון המערכת באמצעות מנהל התקן של LMK (הפסקת תהליכים בגלל מחסור בזיכרון) בתוך ליבת המערכת, מנגנון נוקשה שתלוי בערכים שמוגדרים בהארדקוד. החל מגרסת ליבה 4.12, מנהל ההתקן LMK הוסר מהליבה של upstream, ומרחב המשתמש lmkd
מבצע משימות של מעקב אחרי הזיכרון והפסקת תהליכים.
מידע על עצירה בלחץ
Android 10 ואילך תומכים במצב lmkd
חדש שמשתמש במוניטורים של מידע על לחץ עצירה בליבה (PSI) כדי לזהות לחץ על הזיכרון. ערכת התיקונים של PSI בקרנל במעלה הזרם (backported לקרנלים 4.9 ו-4.14) מודדת את משך הזמן שבו המשימות מתעכבות כתוצאה ממחסור בזיכרון. העיכובים האלה משפיעים ישירות על חוויית המשתמש, ולכן הם מדד נוח לקביעת רמת החומרה של העומס על הזיכרון. ה-kernel של upstream כולל גם כלי מעקב אחר PSI שמאפשרים לתהליכים במרחב המשתמש עם הרשאות (כמו lmkd
) לציין ערכי סף לעיכובים האלה ולהירשם לאירועים מה-kernel כשערך סף נחצה.
מעקב אחר PSI לעומת אותות vmpressure
מכיוון שאותות vmpressure
(שנוצרים על ידי ליבת המערכת לזיהוי עומס על הזיכרון ומשמשים את lmkd
) כוללים לעיתים קרובות הרבה תוצאות חיוביות שגויות, lmkd
צריך לבצע סינון כדי לקבוע אם הזיכרון נמצא תחת עומס אמיתי.
כתוצאה מכך, מתבצעות lmkd
התעוררויות מיותרות ונעשה שימוש במשאבי מחשוב נוספים. השימוש ב-PSI monitors מאפשר לזהות בצורה מדויקת יותר את העומס על הזיכרון ומצמצם את התקורה של הסינון.
שימוש במוניטורים של PSI
כדי להשתמש בנתוני PSI במקום באירועי vmpressure
, צריך להגדיר את המאפיין ro.lmk.use_psi
. ברירת המחדל היא true
, ולכן PSI הוא מנגנון ברירת המחדל לזיהוי עומס על הזיכרון ב-lmkd
. מכיוון שנדרשת תמיכה בליבה כדי להשתמש במדדי PSI, הליבה צריכה לכלול את תיקוני ה-backport של PSI, והיא צריכה להיות מהודרת עם תמיכה ב-PSI (CONFIG_PSI=y
).
חסרונות של מנהל התקן LMK בתוך הליבה
הוצאה משימוש של מנהל ההתקן LMK ב-Android נובעת מכמה בעיות, כולל:
- היה צריך לבצע התאמות אגרסיביות במכשירים עם זיכרון RAM נמוך, וגם אז הביצועים שלהם היו נמוכים בעומסי עבודה עם מטמון דפים פעיל גדול שמגובה בקובץ. הביצועים הגרועים גרמו לשימוש מוגזם בדיסק ולכך שלא היו הריגות.
- מנהל ההתקן של ליבת LMK הסתמך על מגבלות של זיכרון פנוי, ללא שינוי בהתאם לעומס על הזיכרון.
- בגלל העיצוב הנוקשה, השותפים התאימו אישית את מנהל ההתקן כדי שהוא יפעל במכשירים שלהם.
- הדрайבר של LMK התחבר ל-API של slab shrinker, שלא תוכנן לפעולות כבדות כמו חיפוש של יעדים והפסקת הפעולה שלהם, ולכן הוא האט את התהליך של
vmscan
.
Userspace lmkd
מרחב המשתמש lmkd
מיישם את אותה פונקציונליות כמו מנהל ההתקן בתוך הליבה, אבל הוא משתמש במנגנונים קיימים של הליבה כדי לזהות ולהעריך את העומס על הזיכרון. מנגנונים כאלה כוללים שימוש באירועי vmpressure
שנוצרו על ידי ליבת המערכת או במוניטורים של מידע על לחץ עצירה (PSI) כדי לקבל התראות על רמות לחץ הזיכרון, ושימוש בתכונות של קבוצות בקרה של זיכרון כדי להגביל את משאבי הזיכרון שהוקצו לכל תהליך על סמך חשיבות התהליך.
שימוש ב-lmkd במרחב המשתמש ב-Android 10
ב-Android 9 ואילך, מרחב המשתמש lmkd
מופעל אם לא מזוהה דרייבר LMK בתוך הליבה. בגלל שמרחב המשתמש lmkd
דורש תמיכה בליבה ב-cgroups של זיכרון, צריך לקמפל את הליבה עם הגדרות התצורה הבאות:
CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
ביטול אסטרטגיות
מרחב המשתמש lmkd
תומך באסטרטגיות להפסקת פעולה שמבוססות על אירועים vmpressure
או על צגים של PSI, על חומרת האירועים ועל רמזים אחרים כמו ניצול הזיכרון הווירטואלי. יש הבדל בין אסטרטגיות ההשבתה במכשירים עם זיכרון נמוך לבין אסטרטגיות ההשבתה במכשירים עם ביצועים גבוהים:
- במכשירים עם זיכרון נמוך, המערכת צריכה לסבול עומס גבוה יותר על הזיכרון כמצב פעולה רגיל.
- במכשירים עם ביצועים גבוהים, עומס על הזיכרון צריך להיחשב כמצב לא תקין ולטפל בו לפני שהוא משפיע על הביצועים הכוללים.
אפשר להגדיר את אסטרטגיית ההשבתה באמצעות המאפיין ro.config.low_ram
.
בנוסף, במרחב המשתמש lmkd
יש תמיכה במצב מדור קודם שבו מתקבלות החלטות לגבי סגירת תהליכים באמצעות אותן אסטרטגיות שמשמשות את מנהל ההתקן LMK בתוך הליבה (כלומר, זיכרון פנוי וערכי סף של מטמון קבצים). כדי להפעיל את מצב Legacy, מגדירים את המאפיין 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 (תיקוני backport זמינים בליבות המשותפות של Android בגרסאות 4.9, 4.14 ו-4.19).
- כוללים תיקונים לתמיכה ב-PIDFD (תיקונים חוזרים זמינים בליבות הנפוצות של Android בגרסאות 4.9, 4.14 ו-4.19).
- במכשירים עם זיכרון RAM נמוך, צריך לכלול cgroups של זיכרון.
צריך לקמפל את הליבה עם הגדרות התצורה הבאות:
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 stall, באלפיות השנייה, להפעלת התראות קריטיות לגבי זיכרון. אם המכשיר מקבל התראות על עומס זיכרון קריטי מאוחר מדי, כדאי להקטין את הערך הזה כדי שההתראות יופעלו מוקדם יותר. אם התראות על עומס זיכרון קריטי מופעלות שלא לצורך, מגדילים את הערך הזה כדי שהמכשיר יהיה פחות רגיש לרעשי רקע. | 700 |
|
ro.lmk.thrashing_limit |
הכמות המקסימלית של שגיאות חוזרות ב-workingset כאחוז מהגודל הכולל של מטמון הדפים שגובה על ידי קובץ. אם הערך של Workingset refaults גבוה מהערך הזה, המשמעות היא שהמערכת מבצעת פעולות thrashing במטמון הדפים שלה. אם העומס על הזיכרון משפיע על הביצועים של המכשיר, צריך להקטין את הערך כדי להגביל את התופעה של החלפת דפים תכופה מדי. אם הביצועים של המכשיר מופסקים שלא לצורך בגלל פעולות שגורמות לשימוש מוגזם בזיכרון, צריך להגדיל את הערך כדי לאפשר יותר פעולות כאלה. | 100 |
30 |
ro.lmk.thrashing_limit_decay |
הסף של תופעת ה-thrashing, שמוצג כאחוז מהסף המקורי, משמש להורדת הסף כשהמערכת לא משתקמת, גם אחרי הפסקת הפעולה. אם פעולת ה-thrashing הרציפה גורמת להפסקות מיותרות, צריך להקטין את הערך. אם התגובה לשימוש יתר רציף אחרי הפסקת הפעולה איטית מדי, צריך להגדיל את הערך. | 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 |