התהליך Android low memory killer daemon (lmkd
) עוקב אחרי מצב הזיכרון של מערכת Android שפועלת, ומגיב ללחץ זיכרון גבוה על ידי סגירת התהליכים הכי פחות חיוניים כדי לשמור על רמת ביצועים מקובלת במערכת.
מידע על לחץ זיכרון
במערכת Android שמפעילה כמה תהליכים במקביל, יכולות להיות מצבים שבהם זיכרון המערכת מתרוקן ותהליכים שדורשים יותר זיכרון נתקלים בעיכובים ניכרים. לחץ על הזיכרון, מצב שבו למערכת נגמר הזיכרון, מחייב את Android לפנות זיכרון (כדי להקל על הלחץ) על ידי ויסות נתונים (throttle) או סיום של תהליכים לא חשובים, בקשה מתהליכים לפנות משאבים לא קריטיים שנשמרו במטמון וכו'.
בעבר, מערכת Android פקדה על לחץ הזיכרון במערכת באמצעות מנהל בתוך הליבה (LMK), מנגנון נוקשה שמבוסס על ערכים מקודדים מראש. החל מגרסה 4.12 של הליבה, מנהל ההתקן LMK הוסר מהליבה של המקור, ומרחב המשתמש 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 דורשים תמיכה בליבה, הליבה צריכה לכלול את התיקונים של PSI backport ולהיות מתוזמן עם תמיכה ב-PSI מופעלת (CONFIG_PSI=y
).
החסרונות של מנהל LMK בליבה
מערכת Android מפסיקה את השימוש ב-LMK driver בגלל מספר בעיות, כולל:
- במכשירים עם זיכרון RAM נמוך היה צריך לבצע התאמה אגרסיבית, וגם אז הביצועים היו נמוכים בעומסי עבודה עם pagecache פעיל גדול שמבוסס על קובץ. הביצועים הירודים הובילו לטרחה (thrashing) וללא הריגות.
- מנהל הליבה של LMK הסתמך על מגבלות של זיכרון פנוי, ללא התאמה על סמך לחץ הזיכרון.
- בגלל הנוקשות של העיצוב, השותפים התאימו אישית את מנהל ההתקן כדי שיפעל במכשירים שלהם.
- מנהל ה-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
.
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 מתייחס לרמות השימוש במשאבי הזיכרון ולטראשינג כדי למנוע מצב של מחסור בזיכרון ופגיעה בביצועים.
שיטת ההוצאה משימוש הזו מחליפה את השיטות הקודמות, וניתן להשתמש בה במכשירים עם ביצועים גבוהים ובמכשירים עם נפח זיכרון RAM נמוך (Android Go).
דרישות הליבה
במכשירי Android 11, lmkd
מחייב את תכונות הליבה הבאות:
- הוספת תיקוני PSI והפעלת PSI (גרסאות backport זמינות בליבות הנפוצות של 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 refaults גבוה מהערך הזה, המשמעות היא שהמערכת נמצאת במצב של טרישה (thrashing) של pagecache. אם הביצועים של המכשיר מושפעים במהלך לחץ זיכרון, צריך להקטין את הערך כדי להגביל את הטרישה. אם הביצועים של המכשיר נפגעים ללא צורך בגלל טרישה, צריך להגדיל את הערך כדי לאפשר יותר טרישה. | 100 |
30 |
ro.lmk.thrashing_limit_decay |
הירידה של סף הטרחה (thrashing) שמוצגת כאחוז מהסף המקורי, שמשמשת להקטנת הסף כשהמערכת לא מתאוששת גם אחרי הפסקה. אם טרישה מתמשכת יוצרת הפסקות מיותרות, צריך להקטין את הערך. אם התגובה לטרחה רציפה אחרי '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 |