במסמך הזה נסביר איך לזהות ולפתור בעיות מרכזיות בביצועים של האפליקציה.
בעיות מרכזיות בביצועים
יש הרבה בעיות שיכולות לגרום לביצועים נמוכים באפליקציה, אבל ריכזנו כאן כמה בעיות נפוצות שכדאי לחפש באפליקציה:
- זמן האחזור בזמן ההפעלה
זמן האחזור בזמן ההפעלה הוא משך הזמן שחולף בין הקשה על סמל האפליקציה, ההתראה או נקודת כניסה אחרת לבין הצגת הנתונים של המשתמש במסך.
כדאי לכם להתמקד ביעדים הבאים לאפליקציות שלכם:
הפעלה במצב התחלתי (cold start) תוך פחות מ-500 אלפיות השנייה. הפעלה במצב התחלתי מתרחשת כשהאפליקציה שמפעילים לא נמצאת בזיכרון המערכת. האירוע הזה מתרחש כשזו הפעם הראשונה שהאפליקציה מופעלת מאז ההפעלה מחדש או מאז שהמשתמש או המערכת הפסיקו את תהליך האפליקציה.
לעומת זאת, הפעלה במצב ביניים מתרחשת כשהאפליקציה כבר פועלת ברקע. הפעלה קרה דורשת את רוב העבודה מהמערכת, כי היא צריכה לטעון את כל מה שמאוחסן ולהפעיל את האפליקציה. נסו להפעיל את האפליקציה תוך 500 אלפיות השנייה או פחות.
זמני האחזור של P95 ו-P99 קרובים מאוד לזמן האחזור החציוני. אם האפליקציה נפתחת באיטיות, חוויית המשתמש נפגעת. תקשורת בין תהליכים (IPC) וקלט/פלט (I/O) מיותרים במהלך הנתיב הקריטי של הפעלת האפליקציה עלולים להיתקל בבעיות של נעילה וחוסר עקביות.
- תנודות בזמן גלילה
Jank הוא המונח שמתאר את הבעיה החזותית שמתרחשת כשהמערכת לא מצליחה ליצור ולספק פריימים בזמן כדי לצייר אותם במסך בקצב הנדרש של 60Hz או יותר. הבעיה הזו בולטת במיוחד בזמן גלילה, כשבמקום תנועה חלקה של אנימציה יש תנודות. רעידות מופיעות כשהתנועה מושהית לאורך הדרך לפרק זמן של פריים אחד או יותר, כי זמן העיבוד של התוכן באפליקציה ארוך יותר ממהלך הזמן של פריים במערכת.
האפליקציות חייבות לטרגט לקצב רענון של 90Hz. קצבי הרינדור הרגילים הם 60Hz, אבל הרבה מכשירים חדשים יותר פועלים במצב 90Hz במהלך האינטראקציות של המשתמשים, כמו גלילה. חלק מהמכשירים תומכים בקצב גבוה עוד יותר של עד 120Hz.
כדי לראות את קצב הרענון שבו המכשיר משתמש בכל רגע נתון, מפעילים שכבת-על באמצעות אפשרויות למפתחים > הצגת קצב רענון בקטע ניפוי באגים.
- מעברים לא חלקים
המצב הזה ניכר במהלך אינטראקציות כמו מעבר בין כרטיסיות או טעינת פעילות חדשה. מעברים מהסוג הזה חייבים להיות אנימציות חלקות, ולא לכלול עיכובים או הבהוב חזותי.
- חוסר יעילות בשימוש בחשמל
עבודה מפחיתה את טעינת הסוללה, ועבודה מיותרת מפחיתה את חיי הסוללה.
הקצאות זיכרון, שנובעות מיצירת אובייקטים חדשים בקוד, יכולות לגרום לעבודה משמעותית במערכת. הסיבה לכך היא שגם ההקצאות עצמן דורשות מאמץ מ-Android Runtime (ART), וגם שחרור האובייקטים האלה מאוחר יותר (אוסף אשפה) דורש זמן ומאמץ. גם ההקצאה וגם האיסוף מהירים ויעילים הרבה יותר, במיוחד לגבי אובייקטים זמניים. בעבר, השיטה המומלצת הייתה להימנע מהקצאת אובייקטים כשהדבר אפשרי, אבל מומלץ לעשות מה שהכי מתאים לאפליקציה ולמבנה שלכם. לא מומלץ לחסוך בקצאות ולהסתכן בקוד שלא ניתן לתחזק, בהתאם ליכולות של ART.
עם זאת, הקצאה כזו דורשת מאמץ, ולכן חשוב לזכור שהיא עלולה לגרום לבעיות בביצועים אם מקצים הרבה אובייקטים בלולאה הפנימית.
זיהוי בעיות
אנחנו ממליצים על תהליך העבודה הבא לזיהוי בעיות בביצועים ולפתרון שלהן:
- מזהים את תהליכי חוויית המשתמש החיוניים הבאים ובודקים אותם:
- תהליכי הפעלה נפוצים, כולל ממסוף האפליקציות ומהתראה.
- מסכים שבהם המשתמש גולל בין הנתונים.
- מעברים בין מסכים.
- תהליכים ממושכים, כמו ניווט או הפעלת מוזיקה.
- אפשר לבדוק מה קורה במהלך התהליכים הקודמים באמצעות הכלים הבאים לניפוי באגים:
- Perfetto: מאפשרת לראות מה קורה בכל המכשיר באמצעות נתוני תזמון מדויק.
- Memory Profiler: מאפשר לראות אילו הקצאות זיכרון מתרחשות בערימה.
- Simpleperf: תרשים אש שבו מוצגות קריאות הפונקציות שמנצלות את הכי הרבה מעבד במהלך תקופה מסוימת. אם זיהית פעולה ב-Systrace שנמשכת זמן רב אבל לא ברור למה, אפשר להשתמש ב-Simpleperf כדי לקבל מידע נוסף.
כדי להבין את בעיות הביצועים האלה ולפתור אותן, חשוב לנפות באגים באופן ידני בכל הרצה של בדיקה. אי אפשר להחליף את השלבים הקודמים בניתוח נתונים מצטברים. עם זאת, כדי להבין מה המשתמשים רואים בפועל ולזהות מתי יכולות להתרחש נסיגות, חשוב להגדיר איסוף מדדים בבדיקות אוטומטיות ובשטח:
- תהליכים לסטארט-אפים
- מדדי השדות: זמן ההפעלה של Play Console
- בדיקות מעבדה: בדיקת ההפעלה באמצעות Macrobenchmark
- ג'נק
- מדדי שדה
- מדדי הליבה של Play Console: ב-Play Console אי אפשר לצמצם את המדדים לתהליך משתמש ספציפי. הוא מדווח רק על תנודות כלליות לאורך האפליקציה.
- מדידה בהתאמה אישית באמצעות
FrameMetricsAggregator
: אפשר להשתמש ב-FrameMetricsAggregator
כדי לתעד מדדי תנודות במהלך תהליך עבודה מסוים.
- בדיקות מעבדה
- גלילה באמצעות Macrobenchmark.
- הבדיקה Macrobenchmark אוספת את תזמון המסגרות באמצעות פקודות
dumpsys gfxinfo
שמקפות מסלול משתמש יחיד. זוהי דרך להבין את השינויים בתנודות במהלך תהליך ספציפי של משתמש. המדדים שלRenderTime
, שמדגישים את משך הזמן שנדרש לשרטוט פריימים, חשובים יותר ממספר הפריימים הבעייתיים לזיהוי רגרסיות או שיפורים.
- מדדי שדה
בעיות באימות של קישורים לאפליקציות
קישורים לאפליקציות הם קישורי עומק שמבוססים על כתובת האתר שלכם, ואומתו כשייכים לאתר. ריכזנו כאן כמה סיבות אפשריות לכך שאישורי App Link נכשלים.
- היקפי מסנני Intent: מוסיפים את
autoVerify
למסנני Intent רק לכתובות URL שהאפליקציה יכולה להגיב אליהן. - העברת פרוטוקולים לא מאומתים: הפניות אוטומטיות לא מאומתות בצד השרת ובתת-דומיין נחשבות לסיכוני אבטחה וייכשלו באימות. הן גורמות לכשל בכל הקישורים מסוג
autoVerify
. לדוגמה, הפניה אוטומטית של קישורים מ-HTTP ל-HTTPS, כמו example.com ל-www.example.com, בלי לאמת את הקישורים ל-HTTPS, עלולה לגרום לכישלון האימות. חשוב לאמת את קישורי האפליקציות על ידי הוספת מסנני כוונות. - קישורים שלא ניתן לאמת: הוספת קישורים שלא ניתן לאמת למטרות בדיקה עלולה לגרום לכך שהמערכת לא תאמת את הקישורים לאפליקציה שלכם.
- שרתים לא אמינים: צריך לוודא שהשרתים שלכם יכולים להתחבר לאפליקציות הלקוח.
הגדרת האפליקציה לניתוח ביצועים
חשוב להגדיר את הבדיקה בצורה נכונה כדי לקבל מדדי ביצועים מדויקים, שניתן לחזור עליהם ולפעול לפיהם, מאפליקציה. מומלץ לבדוק את האפליקציה במערכת שדומה לסביבת הייצור ככל האפשר, תוך צמצום מקורות הרעש. בקטעים הבאים מפורטים מספר שלבים ספציפיים ל-APK ולמערכת שאפשר לבצע כדי להכין את ההגדרה לבדיקה, חלקם ספציפיים לתרחיש לדוגמה.
נקודות מעקב
אפשר להוסיף לאפליקציות אירועי מעקב בהתאמה אישית.
בזמן תיעוד העקבות, מתבצע עומס קטן של כ-5μs לכל קטע, לכן אל תוסיפו את העקבות לכל שיטה. מעקב אחרי קטעי עבודה גדולים יותר של יותר מ-0.1ms יכול לספק תובנות משמעותיות לגבי צווארי בקבוק.
שיקולים לגבי APK
וריאנטים של ניפוי באגים יכולים לעזור בפתרון בעיות ובסמלול של דוגמאות למחסנית, אבל יש להם השפעה חמורה על הביצועים. במכשירים עם Android מגרסה 10 (רמת API 29) ואילך, אפשר להשתמש ב-profileable android:shell="true"
במניפסט כדי להפעיל יצירת פרופילים בגרסאות build של גרסאות זמינות.
משתמשים בהגדרות של צמצום הקוד ברמת הייצור. בהתאם למשאבים שהאפליקציה משתמשת בהם, יכולה להיות לכך השפעה משמעותית על הביצועים. חלק מההגדרות של ProGuard מסירות נקודות מעקב, לכן כדאי להסיר את הכללים האלה מההגדרה שבה אתם מריצים את הבדיקות.
קומפילציה
מפעילים קומפילציה של האפליקציה במכשיר למצב ידוע – בדרך כלל speed
או speed-profile
. לפעילות ברקע בזמן אמת (JIT) יכולה להיות עלות משמעותית של זמן עיבוד, והיא מתרחשת לעתים קרובות אם מתקינים מחדש את קובץ ה-APK בין הרצות הבדיקה. הפקודה הבאה תעזור לכם לעשות זאת:
adb shell cmd package compile -m speed -f com.google.packagename
במצב הידור speed
, האפליקציה מתורגמת באופן מלא. במצב speed-profile
, האפליקציה מקובצת לפי פרופיל של נתיבי הקוד שבהם נעשה שימוש, שנאספים במהלך השימוש באפליקציה. יכול להיות שיהיה קשה לאסוף פרופילים באופן עקבי ומדויק, לכן אם תחליטו להשתמש בהם, חשוב לוודא שהם אוספים את מה שאתם מצפים. הפרופילים נמצאים במיקום הבא:
/data/misc/profiles/ref/[package-name]/primary.prof
בעזרת Macrobenchmark אפשר לציין את מצב הידור ישירות.
שיקולים לגבי המערכת
כדי לבצע מדידות ברמה נמוכה ובאיכות גבוהה, צריך לכייל את המכשירים. להריץ השוואות A/B באותו מכשיר ובאותה גרסת מערכת הפעלה. יכולים להיות הבדלים משמעותיים בביצועים, גם במכשירים מאותו סוג.
במכשירים עם הרשאת root, כדאי להשתמש בסקריפט lockClocks
למדדי Microbenchmark. בין היתר, הסקריפטים האלה מבצעים את הפעולות הבאות:
- מיקום מעבדים בתדר קבוע.
- השבתת ליבות קטנות והגדרת ה-GPU.
- משביתים את הבקרה התרמית.
לא מומלץ להשתמש בסקריפט lockClocks
כדי לבדוק את חוויית המשתמש, כמו השקת אפליקציות, בדיקות DoU ובדיקות jank, אבל הוא יכול להיות חיוני כדי להפחית את הרעש בבדיקות של Microbenchmark.
כשהדבר אפשרי, מומלץ להשתמש במסגרת בדיקה כמו Macrobenchmark, שיכולה לצמצם את הרעש במדדים ולמנוע אי-דיוק במדידה.
הפעלה איטית של האפליקציה: פעילות טרמפולינה מיותרת
פעילות של trampoline יכולה להאריך את זמן ההפעלה של האפליקציה ללא צורך, ולכן חשוב לבדוק אם האפליקציה שלכם מבצעת אותה. כפי שמוצג בתרשים לדוגמה הבא, אחרי activityStart
אחד מופיע activityStart
נוסף מיד אחריו, בלי שהפעילות הראשונה תצייר פריים כלשהו.
זה יכול לקרות גם בנקודת הכניסה להתראות וגם בנקודת כניסה רגילה של ההפעלה של האפליקציה, ולעיתים קרובות ניתן לטפל בבעיה באמצעות ארגון הקוד מחדש (Refactoring). לדוגמה, אם אתם משתמשים בפעילות הזו כדי לבצע הגדרה לפני פעילות אחרת, כדאי להוציא את הקוד הזה לרכיב או לספרייה שניתנים לשימוש חוזר.
הקצאות לא נחוצות שגורמות לGC בתדירות גבוהה
יכול להיות שתראו ב-Systrace שהפעלת האיסוף של שטחי האשפה (GC) מתרחשת בתדירות גבוהה יותר מהצפוי.
בדוגמה הבאה, כל 10 שניות במהלך פעולה ממושכת הן אינדיקציה לכך שהאפליקציה מקצה באופן עקבי במשך זמן רב, אבל ללא צורך:
יכול להיות שתבחינו גם במרבית ההקצאות של מקבץ קריאות ספציפי כשמשתמשים ב-Memory Profiler. אין צורך לבטל את כל ההקצאות באופן אגרסיבי, כי זה עלול להקשות על תחזוקת הקוד. במקום זאת, כדאי להתחיל לטפל בנקודות חמות של הקצאות.
פריימים לא סדירים
צינור עיבוד הנתונים של הגרפיקה מורכב יחסית, ויכולות להיות ניואנסים מסוימים בקביעה אם משתמש יוכל לראות בסופו של דבר פריימים שהוחמצו. במקרים מסוימים, הפלטפורמה יכולה "להציל" פריים באמצעות אגירת נתונים (buffering). עם זאת, אפשר להתעלם מרוב הניואנסים האלה כדי לזהות פריימים בעייתיים מנקודת המבט של האפליקציה.
כשהמסגרות נוצרות עם מעט עבודה נדרשת מהאפליקציה, נקודות המעקב של Choreographer.doFrame()
מתרחשות בקצב של 16.7ms במכשיר עם 60FPS:
אם תרחיקו את התצוגה ותעיינו בנתיב, לפעמים תראו שצילומי הפריימים נמשכים קצת יותר זמן, אבל זה בסדר כי הם לא נמשכים יותר מ-16.7 אלפיות השנייה שהוקצו להם:
כשמבחינים בהפרעה בקצב הרגיל הזה, מדובר בפריים לא יציב, כפי שמוצג באיור 5:
אפשר להתאמן בזיהוי שלהם.
במקרים מסוימים, צריך להגדיל את התצוגה של נקודת מעקב כדי לקבל מידע נוסף על התצוגות שמתרחשת בהן התנפחויות או על הפעולות של RecyclerView
. במקרים אחרים, יכול להיות שתצטרכו לבדוק לעומק.
מידע נוסף על זיהוי פריימים לא חלקים וניפוי באגים של הגורמים להם זמין במאמר עיבוד איטי.
טעויות נפוצות ב-RecyclerView
ביטול התוקף של כל נתוני הגיבוי של RecyclerView
ללא צורך עלול להוביל לזמני עיבוד ארוך של פריימים ולתנודות בפריימים. במקום זאת, כדי לצמצם את מספר התצוגות שצריך לעדכן, צריך לבטל את התוקף רק של הנתונים שמשתנים.
במאמר הצגת נתונים דינמיים מפורטות דרכים להימנע מבקשות notifyDatasetChanged()
יקרות, שמעודדות עדכון של תוכן במקום החלפה שלו לגמרי.
אם לא תומכים כמו שצריך בכל RecyclerView
בתוך רכיב, זה עלול לגרום ליצירה מחדש מלאה של RecyclerView
הפנימי בכל פעם. לכל RecyclerView
פנימי מקונן צריך להגדיר RecycledViewPool
כדי להבטיח שאפשר למחזר תצוגות בין כל RecyclerView
פנימי.
אם לא שומרים מספיק נתונים מראש או לא שומרים אותם בזמן, יכול להיות שהמשתמשים ירגישו מבולבלים כשיגיעו לתחתית רשימת גלילה ויצטרכו להמתין לנתונים נוספים מהשרת. מבחינה טכנית, זה לא נקרא'תנודות' כי לא מתרחש החמצה של מועדים להגשת פריימים. עם זאת, אפשר לשפר באופן משמעותי את חוויית המשתמש על ידי שינוי התזמון והכמות של האחזור מראש, כדי שהמשתמש לא יצטרך להמתין לנתונים.
ניפוי באגים באפליקציה
ריכזנו כאן כמה שיטות שונות לניפוי באגים בביצועי האפליקציה. בסרטון הבא מופיעה סקירה כללית על מעקב אחר מערכת ועל השימוש בפרופילר של Android Studio.
ניפוי באגים בזמן ההפעלה של האפליקציה באמצעות Systrace
סקירה כללית של תהליך ההפעלה של האפליקציה מופיעה במאמר זמן ההפעלה של האפליקציה, וסקירה כללית של מעקב אחר מערכת מופיעה בסרטון הבא.
אפשר להבחין בין סוגי חברות סטארט-אפ בשלבים הבאים:
- הפעלה קרה: מתחילים ביצירת תהליך חדש ללא מצב ששמור.
- הפעלה חמה: המערכת יוצרת מחדש את הפעילות תוך שימוש חוזר בתהליך, או יוצרת מחדש את התהליך עם המצב השמור.
- הפעלה חמה: הפעלה מחדש של הפעילות, שמתחילה מהנפח.
מומלץ לתעד את ה-Systrace באמצעות אפליקציית System Tracing במכשיר. ב-Android מגרסה 10 ואילך, משתמשים ב-Perfetto. ל-Android 9 ומטה, משתמשים ב-Systrace. מומלץ גם להציג את קובצי המעקב באמצעות הצגת המעקב של Perfetto באינטרנט. למידע נוסף, ראו סקירה כללית של מעקב המערכת.
הנה כמה פרטים שכדאי לבדוק:
- מעקב אחרי מחלוקת: התחרות על משאבים שמוגנים באמצעות מעקב יכולה לגרום לעיכוב משמעותי בהפעלת האפליקציה.
טרנזקציות של קישורים סנכרוניים: מחפשים טרנזקציות מיותרות בנתיב הקריטי של האפליקציה. אם עסקה מסוימת יקרה, כדאי לעבוד עם צוות הפלטפורמה המשויך כדי לבצע שיפורים.
GC בו-זמנית: האירוע הזה נפוץ וההשפעה שלו קטנה יחסית, אבל אם הוא קורה לעיתים קרובות, כדאי לבדוק אותו באמצעות הכלי לניתוח זיכרון של Android Studio.
קלט/פלט: בודקים אם בוצעו פעולות קלט/פלט במהלך ההפעלה, ומחפשים עיכובים ארוכים.
פעילות משמעותית בשרשור אחר: פעילות כזו עלולה להפריע לשרשור של ממשק המשתמש, לכן חשוב לשים לב לעבודות ברקע במהלך ההפעלה.
כדי לשפר את הדיווח על מדדי ההפעלה של האפליקציה, מומלץ להתקשר למספר reportFullyDrawn
אחרי ההפעלה מנקודת המבט של האפליקציה. מידע נוסף על השימוש ב-reportFullyDrawn
זמין בקטע זמן להצגה מלאה.
אפשר לחלץ זמני התחלה שהוגדרו ב-RFD באמצעות מעבד המעקב של Perfetto, וייוצר אירוע מעקב שגלוי למשתמשים.
שימוש ב-System Tracing במכשיר
אפשר להשתמש באפליקציה ברמת המערכת שנקראת System Tracing כדי לתעד מעקב אחרי מערכת במכשיר. האפליקציה הזו מאפשרת להקליט עקבות מהמכשיר בלי לחבר אותו לחשמל או ל-adb
.
שימוש בכלי לניתוח ביצועי הזיכרון ב-Android Studio
אפשר להשתמש בכלי לניהול זיכרון ב-Android Studio כדי לבדוק את לחץ הזיכרון שעלול להיגרם מדליפות זיכרון או מדפוסי שימוש שגויים. הוא מספק תצוגה בזמן אמת של הקצאות האובייקטים.
כדי לפתור בעיות זיכרון באפליקציה, אפשר להיעזר במידע שמתקבל מ-Memory Profiler כדי לעקוב אחרי הסיבות ל-GC ותדירות האירועים האלה.
כדי ליצור פרופיל של זיכרון האפליקציה:
זיהוי בעיות בזיכרון.
מתעדים סשן של יצירת פרופיל זיכרון של תהליך שעובר המשתמש שרוצים להתמקד בו. כדאי לחפש עלייה במספר האובייקטים, כפי שמוצג באיור 7, שמובילה בסופו של דבר לפעולות GC, כפי שמוצג באיור 8.
אחרי שמזהים את תהליך השימוש של המשתמש שגורם ללחץ על הזיכרון, בודקים מהם הגורמים ללחץ על הזיכרון.
אבחון של נקודות חמות של לחץ זיכרון.
בוחרים טווח בקו הזמן כדי להציג גרפית גם את הקצאות וגם את הגודל השטוח, כפי שמוצג באיור 9.
יש כמה דרכים למיין את הנתונים האלה. בהמשך מופיעות כמה דוגמאות לאופן שבו כל תצוגה מפורטת יכולה לעזור לכם לנתח בעיות.
סידור לפי סיווג: שימושי כשרוצים למצוא כיתות שיוצרות אובייקטים שאחרת מאוחסנים במטמון או נעשה בהם שימוש חוזר ממאגר זיכרון.
לדוגמה, אם אתם רואים אפליקציה שיוצרת 2,000 אובייקטים מהסוג Vertex בכל שנייה, היא מגדילה את מספר ההקצאות ב-2,000 בכל שנייה, והיא תופיע כשתמיינו לפי סוג. אם רוצים לעשות שימוש חוזר באובייקטים האלה כדי להימנע מיצירת 'זבל', צריך להטמיע מאגר זיכרון.
סידור לפי סטאק קריאות: שימושי כשרוצים למצוא נתיב חם שבו מתבצעת הקצאת זיכרון, למשל בתוך לולאה או בתוך פונקציה ספציפית שמבצעת הרבה עבודות הקצאה.
Shallow Size: מעקב רק אחרי הזיכרון של האובייקט עצמו. הוא שימושי למעקב אחרי כיתות פשוטות שמכילות בעיקר ערכים פרימיטיביים בלבד.
Retained Size: נפח הזיכרון הכולל שנדרש לאובייקט ולהפניות שמפנות רק לאובייקט. היא שימושית למעקב אחרי לחץ בזיכרון עקב אובייקטים מורכבים. כדי לקבל את הערך הזה, לוקחים את תמונת המצב המלאה של הזיכרון, כפי שמוצג באיור 10, ו-Retained size נוסף כעמודה, כמו שמוצג באיור 11.
מדידת ההשפעה של אופטימיזציה.
קל יותר לזהות את פעולות ה-GC ולהעריך את ההשפעה של אופטימיזציות של זיכרון. כשאופטימיזציה מפחיתה את לחץ על הזיכרון, רואים פחות GC.
כדי למדוד את ההשפעה של האופטימיזציה, מודדים את הזמן בין פעולות GC בקו הזמן של הכלי למעקב אחר ביצועים. לאחר מכן, תוכלו לראות שהזמן שחולף בין פעולות ה-GC ארוך יותר.
השיפורים בזיכרון משפיעים על הדברים הבאים:
- אם האפליקציה לא משפיעה כל הזמן על הלחץ על הזיכרון, סביר להניח שכיבויים שחסרים בזיכרון יצטמצמו.
- פחות GCs משפר את מדדי ה-jank, במיוחד ב-P99. הסיבה לכך היא שפעולות GC גורמות להתנגשות על משאבי המעבד, דבר שעלול לגרום לדחיית משימות רינדור בזמן ביצוע פעולת ה-GC.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- ניתוח והתאמה אישית של הפעלת האפליקציה {:#app-startup-analysis-optimization}
- פריימים קפואים
- כתיבה של Macrobenchmark