בודק ביצועים – גישה יעילה לנתוני ביצועים

מארק כהן

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

  • ניתוח ביצועים אופליין ובהתאמה אישית
  • כלים של צד שלישי לניתוח ביצועים ולהצגה חזותית
  • הערכת ביצועים משולבת בסביבות פיתוח משולבות (IDE) ובכלים אחרים למפתחים

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

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

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

<html>
<head>
    <script>
    var observer = new PerformanceObserver(list => {
        list.getEntries().forEach(entry => {
        // Display each reported measurement on console
        if (console) {
            console.log("Name: "       + entry.name      +
                        ", Type: "     + entry.entryType +
                        ", Start: "    + entry.startTime +
                        ", Duration: " + entry.duration  + "\n");
        }
        })
    });
    observer.observe({entryTypes: ['resource', 'mark', 'measure']});
    performance.mark('registered-observer');

    function clicked(elem) {
        performance.measure('button clicked');
    }
    </script>
</head>
<body>
    <button onclick="clicked(this)">Measure</button>
</body>
</html>

הדף הפשוט מתחיל בתג סקריפט שמגדיר קוד JavaScript:

  • אנחנו יוצרים אובייקט PerformanceObserver חדש ומעבירים פונקציית handler של אירועים לבונה האובייקטים. ה-constructor מפעיל את האובייקט כך שה-handler שלנו יופעל בכל פעם שקבוצה חדשה של נתוני מדידה מוכנה לעיבוד (ונתוני המדידה מועברים כרשימה של אובייקטים). ה-handler מוגדר כאן כפונקציה אנונימית, שפשוט מציגה את נתוני המדידה המעוצבים במסוף. בתרחיש בעולם האמיתי, יכול להיות שהנתונים האלה יאוחסנו בענן לצורך ניתוח נוסף, או יצוינו בכלי אינטראקטיבי להצגה חזותית.
  • אנחנו נרשמים לסוגים של אירועי התזמון שמעניינים אותנו באמצעות השיטה observe(), וקוראים לשיטה mark() כדי לסמן את הרגע שבו נרשמנו, ואנחנו נשקול את ההתחלה של מרווחי הזמן שלנו.
  • אנחנו מגדירים handler של קליקים ללחצן שמוגדר בגוף הדף. ה-handler של הקליקים מפעיל את השיטה measure() כדי לתעד נתוני תזמון לגבי הקליק על הלחצן.

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

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

משתמש לצפייה בביצועים.

הערך start מייצג את חותמת הזמן הראשונית של אירועים מסוג mark (שמתוכם יש רק אירוע אחד באפליקציה). לאירועים מסוג measure אין שעת התחלה מובנית. הם מייצגים מדידות תזמון שבוצעו ביחס לאירוע mark האחרון. לכן, ערכי משך הזמן שמוצגים כאן מייצגים את הזמן שחלף בין הקריאה ל-mark(), שמשמשת כנקודת התחלה של מרווח זמן, וכמספר קריאות נוספות אל measure().

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