שיפורים באנדרואיד 8.0 ART

זמן הריצה של אנדרואיד (ART) שופר באופן משמעותי במהדורת אנדרואיד 8.0. הרשימה שלהלן מסכמת שיפורים שיצרני מכשירים יכולים לצפות ב-ART.

אוסף אשפה דחיסה במקביל

כפי שהוכרז ב-Google I/O, ART כולל אספן אשפה (GC) חדש ב-Android 8.0. אספן זה דוחס את הערימה בכל פעם ש-GC פועל ובזמן שהאפליקציה פועלת, עם הפסקה קצרה אחת בלבד לעיבוד שורשי החוטים. להלן היתרונות שלו:

  • GC תמיד דוחסת את הערימה: גדלים קטנים יותר ב-32% בממוצע בהשוואה לאנדרואיד 7.0.
  • הדחיסה מאפשרת הקצאת אובייקטים של מצביע bump local thread: ההקצאות מהירות יותר ב-70% מאשר באנדרואיד 7.0.
  • מציע זמני הפסקה קטנים ב-85% עבור רף H2 בהשוואה לאנדרואיד 7.0 GC.
  • זמני ההשהיה אינם מתקדמים יותר עם גודל הערימה; אפליקציות צריכות להיות מסוגלות להשתמש בערימות גדולות מבלי לדאוג לגבי ג'אנק.
  • פרטי הטמעת GC - קרא מחסומים:
    • מחסומי קריאה הם כמות קטנה של עבודה שנעשתה עבור כל שדה אובייקט שנקרא.
    • אלה עוברים אופטימיזציה במהדר, אך עשויים להאט כמה מקרי שימוש.

אופטימיזציות לולאות

מגוון רחב של אופטימיזציות לולאות מועסקות על ידי ART במהדורת אנדרואיד 8.0:

  • גבולות בודקים חיסולים
    • סטטי: הוכח שהטווחים נמצאים בגבולות בזמן ההידור
    • דינמי: מבחני זמן ריצה מבטיחים שהלולאות נשארות בגבולות (מחליטים אחרת)
  • חיסול משתני אינדוקציה
    • הסר אינדוקציה מתה
    • החלף אינדוקציה המשמשת רק לאחר הלולאה בביטויים בצורה סגורה
  • חיסול קוד מת בתוך גוף הלולאה, הסרה של לולאות שלמות שמתות
  • הפחתת כוח
  • טרנספורמציות לולאות: היפוך, החלפה, פיצול, פתיחה, חד מודולרי וכו'.
  • SIMDization (נקרא גם וקטוריזציה)

אופטימיזציית הלולאה שוכנת במעבר אופטימיזציה משלו במהדר ART. רוב אופטימיזציות הלולאה דומות לאופטימיזציות ולפישוט במקומות אחרים. אתגרים מתעוררים עם כמה אופטימיזציות המשכתבות את ה-CFG בצורה משוכללת יותר מהרגיל, מכיוון שרוב כלי העזר ל-CFG (ראה nodes.h) מתמקדים בבניית CFG, לא בשכתוב אחד.

ניתוח היררכיה בכיתה

ART באנדרואיד 8.0 משתמש ב-Class Hierarchy Analysis (CHA), אופטימיזציה של מהדר שמבטלת שיחות וירטואליות לשיחות ישירות על סמך המידע שנוצר על ידי ניתוח היררכיות מחלקות. שיחות וירטואליות הן יקרות מכיוון שהן מיושמות סביב בדיקת vtable, והן לוקחות כמה עומסים תלויים. גם שיחות וירטואליות לא יכולות להיות מוטבעות.

להלן סיכום של שיפורים קשורים:

  • עדכון סטטוס דינמי של שיטת יישום יחיד - בתום זמן הקישור של המחלקה, כאשר vtable כבר מאוכלס, ART מבצעת השוואה של ערך אחר ערך ל-vtable של מחלקת העל.
  • אופטימיזציה של מהדר - המהדר ינצל את המידע ליישום יחיד של שיטה. אם לשיטה A.foo מוגדר דגל של יישום יחיד, המהדר יהפוך את הקריאה הוירטואלית לכדי קריאה ישירה, ועוד ינסה להטמיע את הקריאה הישירה כתוצאה מכך.
  • אי תוקף קוד קומפילד - גם בסוף זמן הקישור של המחלקה כאשר מידע על יישום יחיד מתעדכן, אם שיטה A.foo שהייתה לה בעבר יישום יחיד אבל הסטטוס הזה אינו חוקי, כל הקוד הקומפילציה תלוי בהנחה ששיטה A. ל-foo יש צורך ביישום יחיד כדי שקוד הקומפילציה שלהם יבוטל.
  • ביטול אופטימיזציה - עבור קוד הידור חי שנמצא על מחסנית, ביטול אופטימיזציה יתחיל כדי לאלץ את הקוד הקומפילציה לא חוקי למצב מתורגמן כדי להבטיח נכונות. ייעשה שימוש במנגנון חדש של דה-אופטימיזציה שהוא הכלאה של דה-אופטימיזציה סינכרונית וא-סינכרונית.

מטמונים מוטבעים בקבצי oat

ART משתמש כעת במטמונים מוטבעים ומייעל את אתרי השיחות שקיימים עבורם מספיק נתונים. תכונת המטמונים המוטבעים מתעדת מידע נוסף על זמן ריצה לפרופילים ומשתמשת בו כדי להוסיף אופטימיזציות דינמיות להידור לפני הזמן.

Dexlayout

Dexlayout היא ספרייה שהוצגה באנדרואיד 8.0 כדי לנתח קבצי dex ולסדר אותם מחדש לפי פרופיל. Dexlayout שואפת להשתמש במידע על פרופיל זמן ריצה כדי לסדר מחדש חלקים של קובץ dex במהלך הידור תחזוקה סרק במכשיר. על ידי קיבוץ חלקים של קובץ ה-dex שאליהם נגישות לעתים קרובות יחד, לתוכניות יכולות להיות דפוסי גישה טובים יותר לזיכרון ממקום משופר, חיסכון ב-RAM וקיצור זמן ההפעלה.

מכיוון שמידע פרופיל זמין כעת רק לאחר הפעלת אפליקציות, dexlayout משולב בהידור במכשיר של dex2oat במהלך תחזוקה סרק.

הסרת מטמון של Dex

עד אנדרואיד 7.0, אובייקט DexCache היה בעל ארבעה מערכים גדולים, פרופורציונליים למספר האלמנטים מסוימים ב-DexFile, כלומר:

  • מחרוזות (הפניה אחת לכל DexFile::StringId),
  • סוגים (הפניה אחת לכל DexFile::TypeId),
  • שיטות (מצביע מקורי אחד לכל DexFile::MethodId),
  • שדות (מצביע מקורי אחד לכל DexFile::FieldId).

מערכים אלו שימשו לשליפה מהירה של אובייקטים שפתרנו בעבר. באנדרואיד 8.0, כל המערכים הוסרו מלבד מערך השיטות.

ביצועי מתורגמן

ביצועי המתורגמן השתפרו משמעותית במהדורת אנדרואיד 7.0 עם הצגת "mterp" - מתורגמן הכולל מנגנון אחזור/פענוח/פרשנות ליבה שנכתב בשפת assembly. Mterp מעוצב על פי המתורגמן המהיר Dalvik, ותומך בזרוע, arm64, x86, x86_64, mips ו-mips64. עבור קוד חישובי, ה-mterp של Art דומה בערך למתורגמן המהיר של Dalvik. עם זאת, במצבים מסוימים זה יכול להיות איטי יותר באופן משמעותי - ואפילו דרמטי:

  1. קרא ביצועים.
  2. מניפולציה של מיתרים ומשתמשים כבדים אחרים בשיטות המוכרות כטבעיות בדלוויק.
  3. שימוש גבוה יותר בזיכרון מחסנית.

אנדרואיד 8.0 מטפל בבעיות אלה.

יותר משולב

מאז אנדרואיד 6.0, ART יכול להטמיע כל קריאה בתוך אותם קבצי dex, אך יכול היה להטמיע רק שיטות עלים מקובצי dex שונים. היו שתי סיבות להגבלה זו:

  1. הטבעה מקובץ dex אחר מחייבת להשתמש ב-dex cache של אותו קובץ dex אחר, בניגוד לאותו קובץ dex, שיכול פשוט לעשות שימוש חוזר ב-dex cache של המתקשר. מטמון ה-dex נחוץ בקוד הידור עבור כמה הוראות כמו קריאות סטטיות, טעינת מחרוזת או עומס מחלקה.
  2. מפות המחסנית מקודדות רק אינדקס שיטה בתוך קובץ ה-dex הנוכחי.

כדי לטפל במגבלות אלה, אנדרואיד 8.0:

  1. מסיר גישת מטמון dex מקוד הידור (ראה גם סעיף "הסרת מטמון Dex")
  2. מרחיב את קידוד מפת הערימה.

שיפורים בסנכרון

צוות ART כיוונן את נתיבי הקוד MonitorEnter/MonitorExit, והפחית את ההסתמכות שלנו על מחסומי זיכרון מסורתיים ב-ARMv8, והחליפו אותם בהוראות חדשות יותר (רכישה/שחרור) במידת האפשר.

שיטות מקומיות מהירות יותר

קריאות מקוריות מהירות יותר לממשק המקור של Java (JNI) זמינות באמצעות ההערות @FastNative ו- @CriticalNative . אופטימיזציות מובנות של זמן ריצה של ART מאיצות את מעברי JNI ומחליפות את סימון ה- !bang JNI שהוצא משימוש. להערות אין השפעה על שיטות שאינן מקוריות והן זמינות רק לקוד שפת Java של הפלטפורמה ב- bootclasspath (ללא עדכונים בחנות Play).

ההערה @FastNative תומכת בשיטות לא סטטיות. השתמש בזה אם שיטה ניגשת ל- jobject כפרמטר או ערך החזרה.

ההערה @CriticalNative מספקת דרך מהירה עוד יותר להפעיל שיטות מקוריות, עם ההגבלות הבאות:

  • שיטות חייבות להיות סטטיות - אין אובייקטים עבור פרמטרים, ערכי החזרה או this מרומז.
  • רק טיפוסים פרימיטיביים מועברים לשיטת הילידים.
  • השיטה המקורית אינה משתמשת בפרמטרים JNIEnv ו- jclass בהגדרת הפונקציה שלה.
  • יש לרשום את השיטה עם RegisterNatives במקום להסתמך על קישור JNI דינמי.

@FastNative יכול לשפר את ביצועי השיטה המקורית עד פי 3, ו- @CriticalNative עד פי 5. לדוגמה, מעבר JNI שנמדד במכשיר Nexus 6P:

הפעלת ממשק מקורי של Java (JNI). זמן ביצוע (בננו-שניות)
JNI רגיל 115
!באנג JNI 60
@FastNative 35
@CriticalNative 25