效能觀察工具 - 有效率地存取成效資料

Marc Cohen

漸進式網頁應用程式可讓開發人員建構新類型的應用程式,提供可靠且高效能的使用者體驗。不過,為了確保網頁應用程式能達到所需的效能目標,開發人員需要存取高解析度的效能評估資料。W3C 效能時間軸規格定義了這種介面,讓瀏覽器可透過程式碼存取低階時間資料。這為一些有趣的用途開啟了新的大門:

  • 離線和自訂成效分析
  • 第三方效能分析和視覺化工具
  • 將效能評估功能整合至 IDE 和其他開發人員工具

大多數主要瀏覽器都已提供這類操作時間資料,可用於導覽時間資源時間使用者時間。最新新增的功能是效能觀察器介面,這基本上是用於以非同步方式收集低層時間資訊的串流介面,因為瀏覽器會收集這類資訊。這個新介面提供許多重要優勢,可取代先前用來存取時間軸的方法:

  • 目前,應用程式必須定期輪詢並比較已儲存的測量資料,這會造成不必要的成本。這個介面會提供回呼。(也就是說,不需要輪詢)。因此,使用此 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 物件例項化,並將事件處理常式函式傳遞至物件建構函式。建構函式會初始化物件,以便每次有新的一組評估資料可供處理時,系統就會呼叫我們的處理常式 (評估資料會以物件清單的形式傳遞)。處理常式在此處定義為匿名函式,只會在控制台中顯示格式化的測量資料。在實際情境中,這類資料可能會儲存在雲端,以利後續分析,或傳送至互動式視覺化工具。
  • 我們會透過 observe() 方法註冊感興趣的計時事件類型,並呼叫 mark() 方法,標示註冊的當下時刻,也就是計時間隔的開始時間。
  • 我們為頁面主體中定義的按鈕定義點擊處理常式。這個點擊處理常式會呼叫 measure() 方法,擷取按鈕點擊時間的時間資料。

在頁面主體中,我們定義按鈕,將點擊事件處理常式指派給 onclick 事件,即可開始使用。

現在,如果我們載入網頁並開啟 Chrome 開發人員工具面板來監控 JavaScript 主控台,每次按下按鈕時,系統就會進行效能評估。由於我們已註冊觀察這類測量,因此會以非同步方式將這些測量值轉送至事件處理常式,而無需輪詢時間軸,並在發生時在控制台中顯示測量值:

效能觀察器。

start 值代表 mark 類型事件的起始時間戳記 (此應用程式只有一個)。類型為 measure 的事件沒有固有的開始時間,而是代表相對於上一個 mark 事件所採取的時間測量。因此,這裡顯示的時間長度值代表從呼叫 mark() 到後續多次呼叫 measure() 之間的間隔時間,這項作業會用於做為常見間隔的起始點。

如您所見,這個 API 相當簡單,可在不進行輪詢的情況下,收集經過篩選的高解析度即時效能資料,這應該能為網路應用程式提供更有效率的效能工具。