גודל הדף הוא רמת הפירוט שבה מערכת ההפעלה מנהלת את הזיכרון. רוב מעבדי ה-CPU של היום תומכים בגודל דף של 4KB, ולכן מערכת ההפעלה Android והאפליקציות שלה תוכננו ונבנו באופן היסטורי כך שיוכלו לפעול עם גודל דף של 4KB. מעבדי ARM תומכים בגודל דף גדול יותר של 16KB, ומ-Android 15 יש ב-AOSP תמיכה גם ב-build של Android עם גודל דף של 16KB. האפשרות הזו צורכת יותר זיכרון, אבל משפרת את ביצועי המערכת. החל מגרסה 15 של Android, האפשרות הזו לא מופעלת כברירת מחדל, אבל היא זמינה בתור מצב למפתחים או כאפשרות למפתחים, כדי ש-OEM ומפתחי אפליקציות יוכלו להתכונן למעבר למצב 16KB בכל מקום בעתיד.
ב-Android 15 ואילך יש תמיכה ב-build של Android עם יישור ELF בגודל 16KB, שפועל עם ליבות בגודל 4KB ו-16KB החל מ-android14-6.1
.
כשמשתמשים בהגדרה הזו עם ליבה של 16 KB, היא צורכת יותר זיכרון אבל משפרת את ביצועי המערכת.
הגדרת מרחב המשתמש של Android ל-16 KB
יש תמיכה בדפים בגודל 16KB רק ביעדים של arm64
עם ליבות בגודל 16KB.
עם זאת, יש גם אפשרות לסימולציה של מרחב משתמש בנפח 16 KB ב-x86_64
עבור Cuttlefish.
ליעדים מסוג arm64
, אם משתמשים ב-Kleaf כדי ליצור את הליבה, --page_size=16k
יוצר את הליבה במצב 16KB.
אם משתמשים ישירות בהגדרות הליבה של Linux, אפשר לבחור דפים של 16 KB על ידי הגדרת CONFIG_ARM64_16K_PAGES
במקום CONFIG_ARM64_4K_PAGES
.
כדי להפעיל תמיכה בגודל דף של 16KB במרחב המשתמש של Android, צריך להגדיר את אפשרויות ה-build הבאות במוצר:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
מסיר את ההגדרה שלPAGE_SIZE
, ומאפשר לרכיבים לקבוע את גודל הדף בזמן הריצה.PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
, שמבטיח שקובצי ELF של הפלטפורמה נוצרים עם התאמה של 16KB. הגודל הזה גדול מהנדרש, כדי להבטיח תאימות עתידית. עם התאמה של ELF ל-16KB, הליבה יכולה לתמוך בגודל דף של 4KB/16KB.
אימות הדגלים של ה-build
אחרי שבוחרים את היעד lunch
, מוודאים שהדגלים של ה-build מוגדרים בצורה נכונה בסביבה:
$ source build/envsetup.sh
$ lunch target
$ get_build_var TARGET_MAX_PAGE_SIZE_SUPPORTED
16384
$ get_build_var TARGET_NO_BIONIC_PAGE_SIZE_MACRO
true
אם שתי הפקודות הקודמות מחזירות את הערכים 16384
ו-true
בהתאמה, דגלים ה-build מוגדרים בצורה נכונה לעבודה עם ליבה של 16 KB. עם זאת, גם אם ה-build עובר, עדיין יכולות להיות בעיות בסביבת זמן הריצה בגלל הבדלים בסביבה של 16 KB.
תכנות מערכת בגודל דף של 16 KB
רוב הקוד בכל מכשיר עם Android לא מתייחס ישירות לגודל הדף. עם זאת, בקוד שעובד עם דפים, התנהגות הקצאת הזיכרון של הליבה משתנה, וצריך לזכור את זה כדי לכתוב קוד שהוא לא רק תואם, אלא גם בעל ביצועים מרביים ושימוש מינימלי במשאבים.
אם קוראים ל-mmap
באזור של 1KB, 2KB או עד 4KB במערכת של 4KB, המערכת שומרת 4KB כדי להטמיע את זה. במילים אחרות, כששולחים בקשה לזיכרון מהליבה, הליבה תמיד צריכה לעגל את הזיכרון המבוקש לגודל הדף הקרוב ביותר. לדוגמה, אם מקצים אזור של 5KB באזור של 4KB, הליבה מקצה 8KB.
בליבה של 16KB, 'הקצוות הנוספים' האלה של הדפים גדולים יותר. לדוגמה, כל ההקצאות האלה, מ-1KB עד 5KB, יוקצו בגודל 16KB כשמשתמשים בליבה בגודל 16KB. אם מבקשים 17KB, המערכת מקצה 32KB.
לדוגמה, במערכת של 4KB, אפשר להקצות שני אזורים אנונימיים של קריאה וכתיבה בגודל 4KB. עם זאת, בליבה (kernel) של 16KB, המשמעות היא הקצאה של שני דפים או 32KB. בליבה (kernel) של 16KB, אם אפשר, אפשר לשלב את האזורים האלה בדף אחד לקריאה או לכתיבה, כך שנעשה שימוש רק ב-16KB, וזהו בזבוז של 8KB בהשוואה למקרה של ליבה (kernel) בגודל 4KB. כדי לצמצם עוד יותר את השימוש בזיכרון, אפשר לשלב עוד דפים. למעשה, במערכת של 16KB שעברה אופטימיזציה מקסימלית, דפים בגודל 16KB דורשים פחות זיכרון מאשר מערכות של 4KB, כי טבלת הדפים היא רבע מהגודל של אותה זיכרון.
בכל פעם שמשתמשים ב-mmap
, חשוב לעגל את הגודל המבוקש לגודל הדף הקרוב ביותר. כך ניתן להבטיח שכל נפח הזיכרון שהליבה מקצה גלוי ישירות למרחב המשתמש בערכי זמן הריצה, במקום לבקש אותו באופן משתמע ולאפשר גישה אליו באופן משתמע או בטעות.
פיתוח ספריות משותפות עם התאמה של ELF בגודל 16KB
כדי ליצור ספריות משותפות שנכללות בפרויקט Android, ההגדרות הקודמות בקטע הפעלת גודל דף של 16KB מספיקות:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
כדי ליצור ספריות משותפות שלא נכללות בפרויקט Android, צריך להעביר את הדגל הזה ל-linker:
-Wl,-z,max-page-size=16384
אימות קובצי אימג' בינאריים וקובצי אימג' מוכנים מראש בהתאמה ל-ELF בגודל 16KB
הדרך הטובה ביותר לאמת את ההתאמה ואת ההתנהגות בזמן הריצה היא לבדוק ולהריץ את הקוד בליבה (kernel) של 16KB. עם זאת, כדי לזהות בעיות מסוימות בשלב מוקדם יותר:
החל מגרסה 16 של Android (AOSP ניסיוני), אפשר להגדיר את
PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true
בזמן ה-build. כדי להתעלם מהן באופן זמני, אפשר להשתמש ב-ignore_max_page_size: true
ב-Android.bp
וב-LOCAL_IGNORE_MAX_PAGE_SIZE := true
ב-Android.mk
. ההגדרות האלה מאמתות את כל הגרסאות המוכנות מראש ומאפשרות לזהות מתי גרסה אחת מתעדכנת אבל לא מותאמת ל-16 KB.אפשר להריץ את הפקודה
atest elf_alignment_test
כדי לאמת את ההתאמה של קובצי ELF במכשיר במכשירים שמריצים את Android מגרסה 15 ואילך.