使用HMTL5 API監控前端性能

jopen 9年前發布 | 7K 次閱讀 HMTL5 HTML5 前端技術

用戶計時API

用戶計時API可以在網頁應用中測量兩個預定義標記之間的性能。開發者僅僅需要分別定義測量的開始和結束標記。可以通過JavaScript對象“performance”提供的函數,對計時位置進行標記。

var measuring_start = performance.now();

通過“now”函數,可以在網頁應用的獲取計時用高精度時間戳。 和該函數類似的是Date對象,它同樣可以獲取當前時間戳。二者的主要區別是時間精度,now函數的返回值的w3c文檔中明確要求,必須能夠表示精確到千 分位小數的毫秒值。另外now函數返回的數值,是從瀏覽器的“瀏覽開始事件(navigationStart)”開始到現在的毫秒數。

performance.now()
35438640.775000006
(new Date()).getTime()
1443063066478

如果希望分析一個圖片的加載性能,可以在圖片的加載(load)事件中設置第二個標記。圖片加載的耗時,就是“measure_start”和“measure_end”兩個變量之間的差值(單位毫秒)。

<html>
    <head>
        <meta charset="utf-8" />
        <title>test timing</title>
    </head>
    <body>
        <img src="http://cdn3.infoqstatic.com/statics_s2_20150922
-0305u1/styles/i/logo_bigger.jpg" alt="image" >
        <script type="text/javascript">
            var measure_start = performance.now();
            document.getElementsByTagName("img")[0].addEventListener
("load", function() {
                var measure_end = performance.now();
                console.log("image load time: " + (measure_end - measure_start) + "ms");
            }, false);
        </script>
    </body>
</html>

訪問這個html之后,可以在控制臺看見輸出:

image load time: 24.395ms

同時,可以和Chrome開發者工具中網絡標簽頁的加載時間做比較:

(點擊放大圖像)

使用HMTL5 API監控前端性能

除了使用now函數直接獲取時間戳之外,Performance接口還提供了標記(mark)函數。開發者可以在任何需要記錄時間的地方創建、清除標記。

performance.mark("start");
…
performance.mark("end");

mark函數不返回任何值,但是后續可以通過標記的名稱來獲取標記的數據。如果要計算標記之間的差值,可以通過“measure”函數來完成。該函數需要三個參數,第一個參數定義了該差值的名稱,第二個和第三個變量指定標記的名稱。同樣,該函數也不返回任何值。

performance.measure("difference", "start", "end");

上面這個例子,計算了“start”和“end”兩個標記之間的差值,并將差值命名為“difference”。需要特別注意的是,這里相同的名稱都會被記錄,不會覆蓋。

前面說到了,mark、measure這兩個函數,不會返回任何值。如果要讀取標記或者測量的內容,需要通過調用Performance接口中的“getEntries”、“getEntriesByType”或者“getEntriesByName”函數讀取。其中“getEntries”返回當前performance對象中保存的所有標記(包括網頁加載的資源)和測量結果;“getEntriesByType”函數通過類型獲取對應的標記;“getEntriesByName”函數通過標記(或者測量結果)名稱來獲取對應的數據。這些函數的返回值是PerformanceEntry對象列表,包含名稱、開始時間、耗時等字段。

例如,如果要獲取所有的標記或者測量結果,可以通過“getEntriesByType”函數獲取:

performance.mark("start");
performance.mark("end");
performance.measure("difference", "start", "end");
var marks = performance.getEntriesByType("mark");
var measures = performance.getEntriesByType("measure");
console.log("===marks===:")
marks.forEach(function(mark) {
    console.log(mark.name + ": " + mark.startTime);
})
console.log("===measures===:")
measures.forEach(function(measure){
    console.log(measure.name + ": " + measure.duration)
})

在瀏覽器(Chrome)控制臺執行后的輸出為:

===marks===:
start: 6805479.590000001
end: 6805479.74
===measures===:
difference: 0.14999999944120646

可以看見,返回的對象中,name字段為設置的標記(測量結果)的名稱,對于標記可以通過startTime獲取標記時間(和前文提到的now函數 一樣,這里返回的時間也是相對于navigationStart事件),對于計算結果,可以通過duration字段獲取計算結果。上面示例中使用的 “mark”、“measure”兩種類型之外,瀏覽器(Chrome、Firefox等)已經支持“resource”類型。也就是說,這些瀏覽器已經 默認幫我們測量了所有外部資源加載的耗時。對于之前示例中的html(包含一個圖片的引用),如果在瀏覽器的控制臺執行下面的js代碼,可以直接看見這個 圖片加載的耗時:

performance.getEntriesByType("resource").forEach(function(r) {
    console.log(r.name + ": " + r.duration)
})

上述代碼輸出(Chrome)為:

http://cdn3.infoqstatic.com/statics_s2_20150922-
0305u1/styles/i/logo_bigger.jpg: 21.696999901905656

這個數據和Chrome開發者工具中網絡標簽頁中對該請求記錄的耗時完全一致。

如果要直接通過標記、測量結果名稱獲取數據,可以通過getEntriesByName函數獲取。需要注意的是,該函數同樣返回的是PerformanceEntry對象數組,需要迭代獲取具體數據。

同樣,Performance接口也提供了移除標記的接口。可以通過clearMarks和clearMeasures函數,刪除之前創建的標記和測量結果。這兩個函數都接收一個可選的名稱參數,如果傳入名稱,則刪除指定名稱的數據,否則清空標記/測量結果。

performance.clearMarks();
performance.mark("start");
performance.mark("end");
var marks = performance.getEntriesByType("mark");
console.log("before clear:")
marks.forEach(function(mark) {
    console.log(mark.name + ": " + mark.startTime);
})
performance.clearMarks("start");
marks = performance.getEntriesByType("mark");
console.log("after clear:")
marks.forEach(function(mark) {
    console.log(mark.name + ": " + mark.startTime);
})

上述代碼執行后的輸出為:

before clear:
start: 9080690.565000001
end: 9080690.575000001
after clear:
end: 9080690.575000001

也就是說,執行了performance.clearMarks("start");之后,“start”標記被清除了。

瀏覽計時API

瀏覽計時API統計了一個網頁從卸載當前文檔開始到加載完畢這整個流程中,每個節點的時間戳。和用戶計時API不同的是,瀏覽器計時API的時間,是標準的時間戳。每個節點的時間戳,都保存在performance.timing對象中。其中包含的每個節點,可以參考下圖:


使用HMTL5 API監控前端性能

console.log(performance.timing.domLoading);
console.log(performance.timing.domComplete);
console.log("load time: " + (performance.timing.domComplete - 
performance.timing.domLoading ));

例如,可以通過獲取domComplete(DOM構建完成)和domLoading(DOM開始構建)的差值,來計算構建DOM樹消耗的時間。

除了timing對象中保存的各個節點加載時間戳,performance對象中還保存了和navigation對象。它保存了當前頁面的加載類型和重定向次數。其中,加載類型類型有:

  • TYPE_NAVIGATE(type == 0):通過點擊鏈接、輸入地址、表單提交、腳本初開啟等方式加載
  • TYPE_RELOAD(type == 1):通過重新加載或者location.reload()操作加載
  • TYPE_BACK_FORWARD(type == 2):通過瀏覽器歷史遍歷操作加載
  • TYPE_RESERVED(type == 255):上面沒有定義的其他方式

如直接打開一個頁面,在控制臺中執行:

console.log(performance.navigation.type);

上述腳本執行后,控制臺會輸出0,表示這是直接打開的一個頁面。再次刷新頁面,重新執行上面的JavaScript片段,則會輸出1,表示這是一次重新加載。

performance.timing.redirectCount記錄了當前頁面經歷的重定向次數。

瀏覽器支持

用戶計時API已經大部分瀏覽器支持,如IE10+、Chrome 25+、Firefox 15+等,但是Safari等瀏覽器還不支持。對于瀏覽計時API,更多的瀏覽器已經支持,包括Chrome、Firefox、IE9+、Safari 8+等等。

來自:http://www.infoq.com/cn/articles/html5-performance-api-monitoring

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!