1. מבוא
העדכון האחרון: 11 במרץ 2021
למה אנחנו צריכים למדוד את הביצועים של צפיות?
תצוגות הן חלק מרכזי באפליקציות ל-Android, שמשפיעות באופן ישיר על חוויית המשתמש. לדוגמה, הפעילות או החלק מכילים את ממשק המשתמש שמכיל את רכיבי התצוגה שבהם המשתמשים מקיימים אינטראקציה. המשתמשים לא יכולים לראות את כל התוכן של ממשק המשתמש עד שהוא מוצג במלואו על המסך. מסכים איטיים וקפואים יפגעו ישירות באינטראקציה של המשתמשים עם האפליקציה ויוצרים חוויית משתמש גרועה.
האם מערכת Firebase Performance Monitoring לא מספקת את מדדי הביצועים האלה כברירת מחדל?
מעקב ביצועים ב-Firebase מתעד באופן אוטומטי נתוני ביצועים מסוימים, כמו שעת ההתחלה של האפליקציה (כלומר, זמן הטעינה של הפעילות הראשונה בלבד) וביצועי רינדור המסך (כלומר פריימים איטיים וקפואים של פעילויות, אבל לא של מקטעים). עם זאת, בדרך כלל לאפליקציות של התחום אין הרבה פעילויות אלא פעילות אחת ומספר מקטעים (Fragments). בנוסף, אפליקציות רבות בדרך כלל מטמיעות תצוגות מותאמות אישית משלהן לתרחישי שימוש מורכבים יותר. לכן, לרוב כדאי להבין איך למדוד את זמן הטעינה ואת ביצועי העיבוד של המסך של פעילויות ושל קטעי קוד (fragments) באמצעות הטמעת מעקב אחר קוד בהתאמה אישית באפליקציה. אפשר להרחיב בקלות את הקודלהב הזה כדי למדוד את הביצועים של רכיבי תצוגה מותאמים אישית.
מה תלמדו
- איך מוסיפים את Firebase Performance Monitoring לאפליקציה ל-Android
- הסבר על הטעינה של פעילות או מקטע
- איך משתמשים במדדים של מעקב אחר קוד בהתאמה אישית כדי למדוד את זמן הטעינה של פעילות או של קטע קוד
- הסבר על רינדור מסך ומהי מסגרת איטית או קפוא
- איך מגדירים מעקבי קוד בהתאמה אישית באמצעות מדדים להקלטת מסכים איטיים או קפואים
- איך רואים את המדדים שנאספו במסוף Firebase
מה צריך להכין
- Android Studio 4.0 ואילך
- מכשיר Android או אמולטור של Android
- Java מגרסה 8 ואילך
2. תהליך ההגדרה
קבלת הקוד
מריצים את הפקודות הבאות כדי לשכפל את קוד הדוגמה של סדנת הקוד הזו. הפעולה הזו תיצור במחשב שלכם תיקייה בשם codelab-measure-android-view-performance
:
$ git clone https://github.com/FirebaseExtended/codelab-measure-android-view-performance.git
$ cd codelab-measure-android-view-performance
אם אין לכם את git במחשב, אתם יכולים גם להוריד את הקוד ישירות מ-GitHub.
מייבאים את הפרויקט measure-view-performance-start
ל-Android Studio. סביר להניח שיופיעו כמה שגיאות הידור (compile) או אזהרה לגבי קובץ google-services.json
חסר. נפתור זאת בקטע הבא בשלב זה.
בשיעור ה-Codelab הזה נשתמש בפלאגין של Firebase Assistant כדי לרשום אפליקציה ל-Android בפרויקט Firebase, ונוסיף את קובצי התצורה, יישומי הפלאגין ורכיבי התלות הנדרשים ל-Firebase לפרויקט Android שלנו — והכול מתוך Android Studio!
קישור האפליקציה ל-Firebase
- עוברים אל Android Studio/עזרה > בדקו אם יש עדכונים כדי לוודא שאתם משתמשים בגרסאות האחרונות של Android Studio ושל Firebase Assistant.
- בוחרים באפשרות כלים > Firebase כדי לפתוח את החלונית Assistant.
- בוחרים באפשרות מעקב אחר ביצועים כדי להוסיף אותה לאפליקציה, ולאחר מכן לוחצים על תחילת העבודה עם מעקב אחר ביצועים.
- לוחצים על Connect to Firebase (קישור ל-Firebase) כדי לקשר את פרויקט Android ל-Firebase (הפעולה הזו תפתח את מסוף Firebase בדפדפן).
- במסוף Firebase, לוחצים על Add project (הוספת פרויקט) ומזינים שם של פרויקט ב-Firebase (אם כבר יש לכם פרויקט ב-Firebase, תוכלו לבחור את הפרויקט הקיים במקום זאת). לוחצים על המשך ומאשרים את התנאים כדי ליצור את פרויקט Firebase ואפליקציית Firebase חדשה.
- לאחר מכן תוצג תיבת דו-שיח כדי לקשר את אפליקציית Firebase החדשה לפרויקט ב-Android Studio.
- חזרה ל-Android Studio, בחלונית Assistant אמור להופיע אישור שהאפליקציה מחוברת ל-Firebase.
הוספת מעקב ביצועים לאפליקציה
בחלונית Assistant ב-Android Studio, לוחצים על Add Performance Monitoring to your app (הוספת מעקב ביצועים לאפליקציה).
אמורה להופיע תיבת דו-שיח עם בקשה לאשר את השינויים. לאחר מכן, Android Studio אמורה לסנכרן את האפליקציה כדי לוודא שכל יחסי התלות הנדרשים נוספו.
בסיום, אמורה להופיע ההודעה על הצלחה בחלונית Assistant ב-Android Studio, עם אישור על כך שכל יחסי התלות מוגדרים בצורה נכונה.
בשלב נוסף, מפעילים את רישום הבאגים לפי ההוראות בשלב '(אופציונלי) הפעלת רישום באגים'. אותן הוראות זמינות גם במסמכים הציבוריים.
3. הפעלת האפליקציה
אם שילבתם בהצלחה את האפליקציה עם Performance Monitoring SDK, עכשיו הפרויקט אמור להדר (compile). ב-Android Studio, לוחצים על הפעלה > מריצים את 'אפליקציה' כדי ליצור ולהפעיל את האפליקציה במכשיר או באמולטור Android המחובר.
לאפליקציה יש שני לחצנים שמובילים אותך ל'פעילות' ול'מקטע' תואמים, כך:
בשלבים הבאים של סדנת הקוד הזו תלמדו איך למדוד את זמן הטעינה ואת ביצועי העיבוד של המסך של הפעילות או של ה-Fragment.
4. הסבר על טעינת פעילות או קטע קוד
בשלב הזה נסביר מה המערכת עושה במהלך הטעינה של פעילות או קטע קוד.
הסבר על הטעינה של פעילות
עבור פעילות, זמן הטעינה מוגדר כזמן שמתחיל ממועד היצירה של אובייקט הפעילות ועד לציור המלא של הפריים הראשון על המסך (זה הזמן שבו המשתמש יראה את ממשק המשתמש המלא של הפעילות בפעם הראשונה). כדי למדוד אם האפליקציה מצוירת במלואה, אפשר להשתמש בשיטה reportFullyDrawn()
כדי למדוד את משך הזמן שחלף בין הפעלת האפליקציה לבין הצגה מלאה של כל המשאבים וההיררכיות של התצוגות.
באופן כללי, כשהאפליקציה שולחת קריאה ל-startActivity(Intent)
, המערכת מבצעת באופן אוטומטי את התהליכים הבאים. כל תהליך נמשך זמן מה, והוא מוסיף למשך הזמן שחולף בין יצירת הפעילות לבין הרגע שבו המשתמש רואה את ממשק המשתמש של הפעילות במסך שלו.
הסבר על טעינת קטע קוד
בדומה לפעילות, זמן הטעינה של קטע קוד מוגדר כזמן שחולף מהרגע שבו הקטע מצורף לפעילות המארחת שלו ועד שהפריים הראשון של תצוגת הקטע מצויר במלואו על המסך.
5. מדידת זמן הטעינה של פעילות
עיכובים בפריים הראשון עלולים להוביל לחוויית משתמש גרועה, לכן חשוב להבין כמה זמן עובר מהרגע שבו המשתמשים לוחצים על 'הבא' ועד שהם רואים את הפריים הראשון. אפשר להשתמש במעקב אחר קוד בהתאמה אישית כדי למדוד את זמן הטעינה הזה:
- מתחילים את המעקב אחר הקוד המותאם אישית (שנקרא
TestActivity-LoadTime
) בכיתה Activity ברגע שיוצרים את אובייקט הפעילות.
TestActivity.Java
public class TestActivity extends AppCompatActivity {
// TODO (1): Start trace recording as soon as the Activity object is created.
private final Trace viewLoadTrace = FirebasePerformance.startTrace("TestActivity-LoadTime");
// ...
}
- משנים את פונקציית ה-callback של
onCreate()
ומקבלים את התצוגה שנוספה על ידי השיטהsetContentView()
.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Current Activity's main View (as defined in the layout xml file) is inflated after this
setContentView(R.layout.activity_test);
// ...
// TODO (2): Get the View added by Activity's setContentView() method.
View mainView = findViewById(android.R.id.content);
// ...
}
- הוספנו הטמעה של
FistDrawListener
, עם שתי פונקציות קריאה חוזרת (callbacks):onDrawingStart()
ו-onDrawingFinish()
(פרטים נוספים עלFirstDrawListener
ועל הגורמים שיכולים להשפיע על הביצועים שלה מופיעים בקטע הבא). רושמים אתFirstDrawListener
בסוף פונקציית ה-callbackonCreate()
של הפעילות. עליך להפסיק אתviewLoadTrace
בonDrawingFinish()
קריאה החוזרת.
TestActivity.Java
// TODO (3): Register the callback to listen for first frame rendering (see
// "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when View drawing is
// finished.
FirstDrawListener.registerFirstDrawListener(mainView, new FirstDrawListener.OnFirstDrawCallback() {
@Override
public void onDrawingStart() {
// In practice you can also record this event separately
}
@Override
public void onDrawingFinish() {
// This is when the Activity UI is completely drawn on the screen
viewLoadTrace.stop();
}
});
- מריצים מחדש את האפליקציה. לאחר מכן מסננים את logcat באמצעות Logging trace metric. מקישים על הלחצן
LOAD ACTIVITY
ומחפשים יומנים כמו:
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)
🎉 כל הכבוד! מדדתם בהצלחה את זמן הטעינה של פעילות ודיווחתם על הנתונים האלה למעקב אחרי הביצועים ב-Firebase. המדד שתועד יוצג במסוף Firebase בהמשך ב-Codelab הזה.
מטרת FirstDrawListener
בקטע שלמעלה רשמנו FirstDrawListener
. המטרה של FirstDrawListener
היא למדוד מתי הפריים הראשון התחיל ונגמר.
היא מטמיעה את ViewTreeObserver.OnDrawListener
ומבטלת את הקריאה החוזרת (callback) של onDraw()
שמופעלת כשעומד להתחיל תהליך שרטוט של עץ התצוגה. לאחר מכן, התוצאה מסתיימת ב-2 קריאות חוזרות (callback) של כלי שירות onDrawingStart()
ו-onDrawingFinish()
.
הקוד המלא של FirstDrawListener
מופיע בקוד המקור של Codelab.
6. מדידת זמן הטעינה של מקטע
מדידת זמן הטעינה של מקטע דומה לאופן שבו אנחנו מודדים אותו עבור פעילות, אבל עם כמה הבדלים קלים. שוב, נגדיר מעקב אחר קוד בהתאמה אישית:
- משנים את קריאת החזרה (callback) של
onAttach()
ומתחילים להקליט אתfragmentLoadTrace
. נקרא למעקב הזהTest-Fragment-LoadTime
.
כפי שהוסבר בשלב קודם, אפשר ליצור את אובייקט ה-Fragment בכל שלב, אבל הוא הופך לפעיל רק כשמחברים אותו לפעילות המארחת שלו.
TestFragment.java
public class TestFragment extends Fragment {
// TODO (1): Declare the Trace variable.
private Trace fragmentLoadTrace;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
// TODO (2): Start trace recording as soon as the Fragment is attached to its host Activity.
fragmentLoadTrace = FirebasePerformance.startTrace("TestFragment-LoadTime");
}
- רושמים את
FirstDrawListener
בקריאה החוזרת (callback)onViewCreated()
. לאחר מכן, בדומה לדוגמה 'פעילות', צריך להפסיק את המעקב ב-onDrawingFinish()
.
TestFragment.java
@Override
public void onViewCreated(@NonNull View mainView, Bundle savedInstanceState) {
super.onViewCreated(mainView, savedInstanceState);
// ...
// TODO (3): Register the callback to listen for first frame rendering (see
// "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when view drawing is
// finished.
FirstDrawListener.registerFirstDrawListener(mainView, new FirstDrawListener.OnFirstDrawCallback() {
@Override
public void onDrawingStart() {
// In practice you can also record this event separately
}
@Override
public void onDrawingFinish() {
// This is when the Fragment UI is completely drawn on the screen
fragmentLoadTrace.stop();
}
});
- מפעילים מחדש את האפליקציה. לאחר מכן, מסננים את ה-Logcat לפי 'מדד מעקב רישום ביומן'. מקישים על הלחצן
LOAD FRAGMENT
ומחפשים יומנים כמו זה שבהמשך:
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)
🎉 מזל טוב! מדדתם בהצלחה את זמן הטעינה של מקטע, ודיווחתם על הנתונים האלה למעקב אחרי הביצועים ב-Firebase. המדד שתועד יוצג במסוף Firebase בהמשך ב-Codelab הזה.
7. הסבר על רינדור מסך ומהי מסגרת איטית או קפוא
רינדור בממשק המשתמש הוא הפעולה של יצירת פריים מהאפליקציה והצגתה על המסך. כדי להבטיח שהאינטראקציה של המשתמש עם האפליקציה תהיה חלקה, האפליקציה צריכה לעבד פריימים במהירות של פחות מ-16 אלפיות השנייה כדי להגיע לקצב של 60 FPS ( למה כדאי 60fps?). אם האפליקציה שלכם סובלת מעיבוד איטי של ממשק המשתמש, המערכת נאלצת לדלג על פריימים והמשתמש ירגיש גמגום באפליקציה. אנחנו קוראים לזה jank.
באופן דומה, פריימים קפואים הם פריימים של ממשק משתמש שזמן הרינדור שלהם ארוך מ-700 אלפיות השנייה. העיכוב הזה הוא בעיה כי האפליקציה נראית תקועה ולא מגיבה לקלט של המשתמש במשך כמעט שנייה שלמה בזמן העיבוד של המסגרת.
8. מדידת הפריימים האיטיים/הקפואים של קטע
במעקב הביצועים ב-Firebase, המערכת מתעדת באופן אוטומטי פריימים איטיים או קפואים בפעילות (רק אם באמצעות חומרה מואצת). עם זאת, התכונה הזו לא זמינה כרגע לקטעי קוד. הפריימים האיטיים/הקפואים של Fragment מוגדרים כפריימים האיטיים או הקפואים של כל הפעילות בין הקריאות החוזרות onFragmentAttached()
ו-onFragmentDetached()
במחזור החיים של ה-Fragment.
בהשראת הכיתה AppStateMonitor
(שנכללת ב-Performance Monitoring SDK ומשמשת להקלטת מעקב מסך לפעילות), הטמענו את הכיתה ScreenTrace
(שנכללת במאגר קוד המקור של ה-codelab הזה). אפשר לחבר את הכיתה ScreenTrace
לקריאה החוזרת של מחזור החיים של FragmentManager
בפעילות כדי לצלם פריימים איטיים או קפואים. בכיתה הזו יש שני ממשקי API ציבוריים:
recordScreenTrace()
: מתחילה הקלטה של מעקב אחר המסךsendScreenTrace()
: הפסקת ההקלטה של מעקב המסך וצירוף מדדים מותאמים אישית לרישום ספירות של 'סך הכול', 'איטי' ו'קפוא'.
אם תצרפו את המדדים המותאמים אישית האלה, תוכלו לטפל בנתוני המעקב אחר המסך של קטעי קוד באותו אופן שבו מטפלים בנתוני המעקב אחר המסך של פעילות, ותוכלו להציג אותם לצד נתוני מעקב אחרים של עיבוד המסך בלוח הבקרה ביצועים במסוף Firebase.
כך מתעדים מעקבות מסך עבור ה-Fragment:
- אתחל את המחלקה
ScreenTrace
בפעילות שלך שמארחת את ה-Fragment.
MainActivity.Java
// Declare the Fragment tag
private static final String FRAGMENT_TAG = TestFragment.class.getSimpleName();
// TODO (1): Declare the ScreenTrace variable.
private ScreenTrace screenTrace;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// TODO (2): Initialize the ScreenTrace variable.
screenTrace = new ScreenTrace(this, FRAGMENT_TAG);
// ...
}
- כשאתם מעלים את ה-Fragment, אתם צריכים לרשום אותו ל-
FragmentLifecycleCallbacks
ולשנות את פונקציות ה-call backonFragmentAttached()
ו-onFragmentDetached()
. עשינו זאת בשבילך. צריך להתחיל להקליט את הטרייסים של המסך בקריאה החוזרתonFragmentAttached()
ולהפסיק את ההקלטה בקריאה החוזרתonFragmentDetached()
.
MainActivity.Java
private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks =
new FragmentManager.FragmentLifecycleCallbacks() {
@Override
public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Context context) {
super.onFragmentAttached(fm, f, context);
// TODO (3): Start recording the screen traces as soon as the Fragment is
// attached to its host Activity.
if (FRAGMENT_TAG.equals(f.getTag()) && screenTrace.isScreenTraceSupported()) {
screenTrace.recordScreenTrace();
}
}
@Override
public void onFragmentDetached(@NonNull FragmentManager fm, @NonNull Fragment f) {
super.onFragmentDetached(fm, f);
// TODO (4): Stop recording the screen traces as soon as the Fragment is
// detached from its host Activity.
if (FRAGMENT_TAG.equals(f.getTag()) && screenTrace.isScreenTraceSupported()) {
screenTrace.sendScreenTrace();
}
// Unregister Fragment lifecycle callbacks after the Fragment is detached
fm.unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks);
}
};
- מפעילים מחדש את האפליקציה. לאחר מכן מקישים על הלחצן
LOAD FRAGMENT
. ממתינים כמה שניות ולוחצים על הסמלback button
בסרגל הניווט התחתון.
מסננים את ה-Logcat באמצעות 'מדד מעקב הרישום ביומן', ולאחר מכן מחפשים את היומנים הבאים:
I/FirebasePerformance: Logging trace metric: _st_MainActivity-TestFragment (duration: XXXms)
מסננים את ה-Logcat באמצעות 'FireperfViews' ומחפשים יומנים כמו:
D/FireperfViews: sendScreenTrace MainActivity-TestFragment, name: _st_MainActivity-TestFragment, total_frames: XX, slow_frames: XX, frozen_frames: XX
🎉 כל הכבוד! הצלחתם למדוד את הפריימים האיטיים/הקפואים של קטע מסוים ולדווח על הנתונים האלה ל-Firebase Performance Monitoring. בהמשך הסדנה נציג את המדדים שתועדו במסוף Firebase.
9. בדיקת המדדים במסוף Firebase
- ב-Logcat, לוחצים על כתובת ה-URL של מסוף Firebase כדי לעבור לדף הפרטים לצורך מעקב.
לחלופין, במסוף Firebase, בוחרים את הפרויקט שבו האפליקציה נמצאת. בחלונית הימנית, מאתרים את האפשרויות פריטי תוכן ו- בקטע 'מעקב', ולאחר מכן לוחצים על ביצועים.
- בכרטיסייה הראשית של מרכז הבקרה, גוללים למטה לטבלת המעקב ולוחצים על הכרטיסייה מעקבים בהתאמה אישית. בטבלה הזו יופיעו מעקבי קודים מותאמים אישית שהוספנו קודם לכן וגם כמה מעקב אחר מחוץ לאריזה כמו מעקב
_app_start
. - מוצאים את שני מעקבי הקוד בהתאמה אישית,
TestActivity-LoadTime
ו-TestFragment-LoadTime
. לוחצים על משך זמן של כל אחת מהן כדי לראות פרטים נוספים על הנתונים שנאספו.
- בדף הפרטים של המעקב אחר הקוד המותאם אישית מוצג מידע על משך המעקב (כלומר, זמן הטעינה שנמדד).
- אפשר גם להציג את נתוני הביצועים של מעקב המסך בהתאמה אישית.
- חוזרים לכרטיסייה הראשית של מרכז הבקרה, גוללים למטה לטבלת המעקב ולוחצים על הכרטיסייה רינדור מסך. בטבלה הזו יופיעו נתוני המעקב המותאם אישית של המסך שהוספנו מקודם, וגם נתוני מעקב מוכנים מראש של המסך, כמו המעקב
MainActivity
. - מחפשים את קו המסך המותאם אישית,
MainActivity-TestFragment
. לוחצים על שם המעקב כדי לראות את הנתונים הנצברים של עיבוד איטי ופריימים קפואים.
10. מזל טוב
כל הכבוד! מדדתם בהצלחה את זמן הטעינה ואת ביצועי עיבוד המסך של פעילות ומקטע נתונים באמצעות מעקב ביצועים ב-Firebase.
ההישגים שלכם
- שילבתם מעקב ביצועים ב-Firebase באפליקציה לדוגמה
- עכשיו אתם מבינים את מחזור החיים של טעינת התצוגה
- מדדתם את זמן הטעינה של פעילות ושל מקטע (Fragment) על ידי הוספת מעקבי קוד בהתאמה אישית.
- תיעדת פריימים איטיים או קפואים על ידי הוספת מעקבי מסך בהתאמה אישית עם מדדים מותאמים אישית
המאמרים הבאים
Firebase Performance מספק דרכים נוספות למדידת הביצועים של האפליקציה, מלבד מעקב מותאם אישית. הוא מודד באופן אוטומטי נתוני ביצועים של זמן הפעלת האפליקציה, של אפליקציה בחזית ושל אפליקציה ברקע. עכשיו הגיע הזמן לבדוק את המדדים האלה במסוף Firebase.
בנוסף, Firebase Performance מציע מעקב אוטומטי אחר בקשות רשת מסוג HTTP/S. כך אפשר לשלוח בקלות בקשות רשת בלי לכתוב שורת קוד אחת. יש לך אפשרות לנסות לשלוח כמה בקשות רשת מהאפליקציה ולמצוא את המדדים במסוף Firebase?
בונוס
עכשיו, אחרי שאתם יודעים איך למדוד את זמן הטעינה ואת ביצועי עיבוד המסך של הפעילות/המקטעים, באמצעות מעקבי קוד בהתאמה אישית, אתם יכולים לעיין בבסיס הקוד הפתוח שלנו כדי לבדוק אם אפשר להוציא את המדדים האלה מהאריזה בכל פעילות או מקטע שנכלל באפליקציה? אפשר לשלוח את ה-PR אם תרצה :-)
11. למידה כבונוס
הבנת התהליך שמתרחש במהלך טעינת הפעילות תעזור לכם להבין טוב יותר את מאפייני הביצועים של האפליקציה. בשלב קודם תיארנו ברמה גבוהה מה קורה במהלך טעינת הפעילות, אבל בתרשים הבא מתוארת כל שלב בפירוט רב יותר.