מדוד זמן טעינה ועיבוד מסך עם ניטור ביצועי Firebase

1. הקדמה

עדכון אחרון: 2021-03-11

למה אנחנו צריכים למדוד את הביצועים של צפיות?

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

האם ניטור הביצועים של Firebase אינו מספק את מדדי הביצועים האלה מחוץ לקופסה?

ניטור הביצועים של Firebase לוכד אוטומטית כמה נתוני ביצועים מחוץ לקופסה, כגון שעת ההתחלה של האפליקציה שלך (כלומר, זמן הטעינה עבור הפעילות הראשונה שלך בלבד) וביצועי עיבוד המסך (כלומר, פריימים איטיים וקפואים עבור פעילויות אך לא עבור שברים). עם זאת, לאפליקציות בתעשייה אין בדרך כלל הרבה פעילויות אלא פעילות אחת ומספר פרגמנטים. כמו כן, אפליקציות רבות מיישמות בדרך כלל תצוגות מותאמות אישית משלהן למקרי שימוש מורכבים יותר. לכן, לעתים קרובות שימושי להבין כיצד למדוד את זמן הטעינה וביצועי רינדור המסך של פעילויות וגם של פרגמנטים על ידי שימוש במעקבי קוד מותאמים אישית באפליקציה שלך. אתה יכול בקלות להרחיב מעבדת קוד זה כדי למדוד את הביצועים של רכיבי תצוגה מותאמת אישית.

מה תלמד

  • כיצד להוסיף ניטור ביצועים של Firebase לאפליקציית אנדרואיד
  • הבנת הטעינה של פעילות או קטע
  • כיצד להכשיר מעקבי קוד מותאמים אישית למדידת זמן הטעינה של פעילות או קטע
  • הבנת עיבוד מסך ומהי מסגרת אטית/קפואה
  • כיצד מכשיר מעקבי קוד מותאמים אישית עם מדדים להקלטת מסכים איטיים/קפואים
  • כיצד להציג את המדדים שנאספו במסוף Firebase

מה אתה צריך

  • Android Studio 4.0 ומעלה
  • מכשיר אנדרואיד/אמולטור
  • 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. סביר להניח שתראה כמה שגיאות קומפילציה או אולי אזהרה לגבי קובץ google-services.json חסר. אנו נתקן זאת בחלק הבא של שלב זה.

במעבדת הקוד הזה, נשתמש בפלאגין Firebase Assistant כדי לרשום את אפליקציית Android שלנו עם פרויקט Firebase ולהוסיף את קבצי התצורה, הפלאגינים והתלות הנדרשים של Firebase לפרויקט Android שלנו - הכל מתוך Android Studio !

חבר את האפליקציה שלך ל-Firebase

  1. עבור אל Android Studio / עזרה > בדוק אם קיימים עדכונים כדי לוודא שאתה משתמש בגרסאות האחרונות של Android Studio וב-Firebase Assistant.
  2. בחר כלים > Firebase כדי לפתוח את חלונית ה- Assistant .

e791bed0999db1e0.png

  1. בחר ניטור ביצועים כדי להוסיף לאפליקציה שלך, ולאחר מכן לחץ על התחל עם ניטור ביצועים .
  2. לחץ על התחבר ל-Firebase כדי לחבר את פרויקט האנדרואיד שלך ל-Firebase (פעולה זו תפתח את קונסולת Firebase בדפדפן שלך) .
  3. במסוף Firebase, לחץ על הוסף פרוייקט ולאחר מכן הזן שם פרוייקט Firebase (אם כבר יש לך פרוייקט Firebase, תוכל לבחור את הפרויקט הקיים במקום זאת) . לחץ על המשך וקבל את התנאים כדי ליצור את פרויקט Firebase ואפליקציית Firebase חדשה.
  4. לאחר מכן, אתה אמור לראות תיבת דו-שיח לחיבור אפליקציית Firebase החדשה שלך לפרויקט Android Studio שלך.

42c498d28ead2b77.png

  1. בחזרה ב-Android Studio, בחלונית Assistant , אתה אמור לראות את האישור שהאפליקציה שלך מחוברת ל-Firebase.

dda8bdd9488167a0.png

הוסף ניטור ביצועים לאפליקציה שלך

בחלונית Assistant ב-Android Studio, לחץ על הוסף ניטור ביצועים לאפליקציה שלך .

אתה אמור לראות תיבת דו-שיח ל'קבל שינויים' שלאחריה Android Studio אמור לסנכרן את האפליקציה שלך כדי להבטיח שכל התלות הדרושות נוספו.

9b58145acc4be030.png

לבסוף, אתה אמור לראות את הודעת ההצלחה בחלונית ה-Assistant ב-Android Studio שכל התלות מוגדרת כהלכה.

aa0d46fc944e0c0b.png

כשלב נוסף, הפעל רישום ניפוי באגים על ידי ביצוע ההוראות בשלב "(אופציונלי) הפעל רישום באגים". אותן הוראות זמינות גם בתיעוד הציבורי .

3. הפעל את האפליקציה

אם שילבת בהצלחה את האפליקציה שלך עם ה-SDK לניטור ביצועים, הפרויקט אמור כעת להדר. ב-Android Studio, לחץ על הפעלה > הפעל 'אפליקציה' כדי לבנות ולהפעיל את האפליקציה במכשיר/אמולטור האנדרואיד המחוברים שלך.

לאפליקציה יש שני כפתורים שלוקחים אותך לפעילות ולקטע תואמים, כך:

410d8686b4f45c33.png

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

4. הבנת הטעינה של פעילות או קטע

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

הבנת הטעינה של פעילות

עבור פעילות, זמן הטעינה מוגדר כזמן שמתחיל מיצירת אובייקט ה-Activity ועד לציור ה- First Frame במלואו על המסך ( זה הזמן שבו המשתמש שלך יראה את ממשק המשתמש המלא של הפעילות בפעם הראשונה זמן ). כדי למדוד אם האפליקציה שלך מצוירת במלואה, אתה יכול להשתמש בשיטת reportFullyDrawn() כדי למדוד את הזמן שחלף בין הפעלת האפליקציה לתצוגה מלאה של כל המשאבים וההיררכיות של התצוגה.

ברמה גבוהה, כאשר האפליקציה שלך קוראת startActivity(Intent) , המערכת מבצעת אוטומטית את התהליכים הבאים. כל תהליך לוקח זמן להשלים, מה שמוסיף למשך הזמן שבין יצירת הפעילות ועד מתי המשתמש רואה את ממשק המשתמש של הפעילות על המסך שלו.

c20d14b151549937.png

הבנת טעינת קטע

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

5. מדוד את זמן הטעינה של פעילות

עיכובים בפריים הראשון עלולים להוביל לחוויית משתמש גרועה, לכן חשוב להבין כמה עיכוב הטעינה הראשוני חווים המשתמשים שלך. אתה יכול מכשיר מעקב קוד מותאם אישית כדי למדוד את זמן הטעינה הזה:

  1. התחל את מעקב הקוד המותאם אישית (ששמו TestActivity-LoadTime ) במחלקה Activity ברגע שאובייקט ה-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");

    // ...

}
  1. עוקף את ההתקשרות חזרה של onCreate() וקבל את ה-View הוספה בשיטת 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);     

    // ...
}
  1. כללנו יישום של FistDrawListener , שיש לו שתי התקשרויות: onDrawingStart() ו- onDrawingFinish() (ראה את הסעיף הבא למטה לפרטים נוספים על FirstDrawListener ומה יכול להשפיע על הביצועים שלו) . רשום את FirstDrawListener בסוף ה- onCreate() התקשרות חוזרת של Activity. עליך לעצור את 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();             
        }         
    });
  1. הפעל מחדש את האפליקציה. לאחר מכן, סנן את ה-logcat באמצעות " מדד מעקב ביומן ". הקש על כפתור LOAD ACTIVITY , וחפש יומנים כמו להלן:
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)

🎉 מזל טוב! מדדת בהצלחה את זמן הטעינה של פעילות ודיווחת על הנתונים האלה לניטור הביצועים של Firebase. אנו נציג את המדד המוקלט במסוף Firebase בהמשך מעבדת הקוד הזה.

מטרת FirstDrawListener

בסעיף למעלה, רשמנו FirstDrawListener . מטרת FirstDrawListener היא למדוד מתי הפריים הראשון התחיל וסיים לצייר.

הוא מיישם את ViewTreeObserver.OnDrawListener ומעקף את ה- onDraw() callback אשר מופעל כאשר עץ ה-View עומד להימשך. לאחר מכן, הוא עוטף את התוצאה כדי לספק שתי התקשרויות של כלי שירות onDrawingStart() ו- onDrawingFinish() .

ניתן למצוא את הקוד המלא עבור FirstDrawListener בקוד המקור של מעבדת קוד זה.

6. מדוד את זמן הטעינה של קטע

מדידת זמן הטעינה של קטע דומה לאופן שבו אנו מודדים אותו עבור פעילות, אך עם כמה הבדלים מינוריים. שוב, נבצע מעקב אחר קוד מותאם אישית :

  1. תעקוף את ההתקשרות חזרה של 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");
   }
  1. רשום את FirstDrawListener בהתקשרות חוזרת של onViewCreated() . לאחר מכן, בדומה לדוגמה של Activity, עצור את המעקב ב- 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();
       }
   });
  1. הפעל מחדש את האפליקציה. לאחר מכן, סנן את ה-logcat באמצעות " מדד מעקב ביומן ". הקש על כפתור LOAD FRAGMENT וחפש יומנים כמו להלן:
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)

🎉 מזל טוב! מדדת בהצלחה את זמן הטעינה של קטע ודיווחת על הנתונים האלה לניטור הביצועים של Firebase. אנו נציג את המדד המוקלט במסוף Firebase בהמשך מעבדת הקוד הזה.

7. הבנת עיבוד מסך ומהי מסגרת אטית/קפואה

עיבוד ממשק משתמש הוא הפעולה של יצירת מסגרת מהאפליקציה שלך והצגתה על המסך. כדי להבטיח שהאינטראקציה של משתמש עם האפליקציה שלך תהיה חלקה, האפליקציה שלך צריכה להציג פריימים בפחות מ-16ms כדי להשיג 60 פריימים לשנייה ( למה 60fps? ). אם האפליקציה שלך סובלת מעיבוד איטי של ממשק משתמש, אז המערכת נאלצת לדלג על פריימים, והמשתמש יתפוס גמגום באפליקציה שלך. אנחנו קוראים לזה ג'נק .

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

8. מדוד את הפריימים האיטיים/קפואים של קטע

ניטור ביצועי Firebase לוכד אוטומטית פריימים איטיים/קפואים עבור פעילות ( אבל רק אם היא מואצת בחומרה ). עם זאת, תכונה זו אינה זמינה כעת עבור Fragments. הפריימים האיטיים/קפואים של Fragment מוגדרים כפריימים האיטיים/קפואים עבור כל הפעילות בין ה- onFragmentAttached() ו- onFragmentDetached() הקריאות חוזרות במחזור החיים של הפרגמנט.

מתוך מוטיבציה ממחלקת AppStateMonitor ( שהיא חלק מ-SDK לניטור ביצועים האחראי על הקלטת מעקבי מסך עבור Activity ), הטמענו את מחלקת ScreenTrace ( שהיא חלק ממאגר קוד מקור זה של מעבדת קוד ). ניתן לחבר את מחלקת ScreenTrace ל-Callback של FragmentManager של הפעילות של מחזור החיים כדי ללכוד פריימים איטיים/קפואים. מחלקה זו מספקת שני ממשקי API ציבוריים:

  • recordScreenTrace() : מתחיל להקליט מעקב מסך
  • sendScreenTrace() : עוצר את ההקלטה של ​​מעקב מסך ומצרף מדדים מותאמים אישית לרישום של ספירות סה"כ, איטיות וקפואות

על ידי צירוף מדדים מותאמים אישית אלה, ניתן לטפל בעקבות מסך עבור Fragments באותו אופן כמו עקבות מסך עבור פעילות וניתן להציג אותם יחד עם מעקבי עיבוד מסך אחרים בלוח המחוונים הביצועים של מסוף Firebase.

הנה איך לרשום עקבות מסך עבור הפרגמנט שלך:

  1. אתחל את מחלקת ScreenTrace בפעילות שלך שמארחת את הפרגמנט.

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);

    // ...
}
  1. כאשר אתה טוען את ה-Fragment שלך, הירשם ל- FragmentLifecycleCallbacks ועקוף את ההתקשרויות onFragmentAttached() ו- onFragmentDetached() . עשינו זאת עבורך. עליך להתחיל להקליט עקבות מסך ב- onFragmentAttached() callback ולהפסיק להקליט ב- onFragmentDetached() callback.

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);
           }
       };
  1. הפעל מחדש את האפליקציה. לאחר מכן, הקש על כפתור 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. אנו נציג את המדדים המוקלטים במסוף Firebase בהמשך מעבדת הקוד הזה.

9. בדוק מדדים במסוף Firebase

  1. ב-logcat, לחץ על כתובת האתר של מסוף Firebase כדי לבקר בדף הפרטים למעקב. ceb9d5ba51bb6e89.jpeg

לחלופין, במסוף Firebase , בחר את הפרויקט הכולל את האפליקציה שלך. בחלונית השמאלית, אתר את הקטע שחרור וניטור ולאחר מכן לחץ על ביצועים .

  • בכרטיסייה הראשית של לוח המחוונים , גלול מטה לטבלת העקבות ולאחר מכן לחץ על הכרטיסייה מעקבים מותאמים אישית . בטבלה זו, תראה את מעקבי הקוד המותאמים אישית שהוספנו קודם לכן בתוספת כמה מעקבים מחוץ לקופסה , כגון _app_start trace.
  • מצא את שני עקבות הקוד המותאמים אישית שלך, TestActivity-LoadTime ו- TestFragment-LoadTime . לחץ על משך הזמן עבור אחד מהם כדי להציג פרטים נוספים על הנתונים שנאספו.

a0d8455c5269a590.png

  1. דף הפרטים של מעקב הקוד המותאם אישית מציג לך מידע על משך המעקב (כלומר, זמן הטעינה הנמדד).

5e92a307b7410d8b.png

  1. אתה יכול גם להציג את נתוני הביצועים עבור מעקב המסך המותאם אישית שלך.
  • חזור לכרטיסייה הראשית של לוח המחוונים , גלול מטה לטבלת העקבות ולאחר מכן לחץ על הכרטיסייה עיבוד מסך . בטבלה זו, תראה את עקבות המסך המותאמים אישית שהוספנו קודם לכן, בתוספת כל עקבות מסך מחוץ לקופסה , כגון MainActivity trace.
  • מצא את מעקב המסך המותאם אישית שלך, MainActivity-TestFragment . לחץ על שם המעקב כדי להציג את הנתונים המצטברים של עיבוד איטי ומסגרות קפואות.

ee7890c7e2c28740.png

10. מזל טוב

מזל טוב! מדדת בהצלחה את זמן הטעינה ואת ביצועי עיבוד המסך של פעילות ופרגמנט באמצעות ניטור ביצועים של Firebase!

מה שהשגת

מה הלאה

Firebase Performance מספק יותר דרכים למדידת ביצועים של האפליקציה שלך מלבד מעקב מותאם אישית. הוא מודד אוטומטית את זמן ההפעלה של האפליקציה, נתוני הביצועים של האפליקציה בחזית ונתוני האפליקציה ברקע . הגיע הזמן שתבדוק את המדדים האלה ב- Firebase Console .

כמו כן, Firebase Performance מציע ניטור אוטומטי של בקשות רשת HTTP/S . עם זה אתה יכול בקלות לכוון בקשות רשת מבלי לכתוב שורת קוד אחת. האם תוכל לנסות לשלוח כמה בקשות רשת מהאפליקציה שלך ולמצוא את המדדים במסוף Firebase ?

מַעֲנָק

כעת, כשאתה יודע למדוד את זמן הטעינה וביצועי עיבוד המסך של הפעילות/פרגמנט שלך על ידי שימוש במעקבי קוד מותאמים אישית, האם אתה יכול לחקור את בסיס הקוד הפתוח שלנו כדי לראות אם אתה יכול ללכוד את המדדים האלה מהקופסה עבור כל פעילות/פרג. זה חלק מהאפליקציה? אתה מוזמן לשלוח את היח"צ אם אתה רוצה :-)

11. לימוד בונוס

הבנת מה קורה במהלך טעינת פעילות תעזור לך להבין טוב יותר את מאפייני הביצועים של האפליקציה שלך. בשלב מוקדם יותר, תיארנו ברמה גבוהה מה קורה במהלך טעינת פעילות, אך התרשים הבא מתאר כל שלב בפירוט הרבה יותר גבוה.

cd61c1495fad7961.png