window.performance
是W3C性能小組引入的新的API,目前IE9以上的瀏覽器都支持。一個performance對象的完整結構以下圖所示:
javascript
memory
字段表明JavaScript對內存的佔用。css
navigation
字段統計的是一些網頁導航相關的數據:html
redirectCount
:重定向的數量(只讀),可是這個接口有同源策略限制,即僅能檢測同源的重定向;最重要的是timing
字段的統計數據,它包含了網絡、解析等一系列的時間數據。java
2.2.1 timing
APIweb
timing
的總體結構以下圖所示:bootstrap
各字段的含義以下:api
startTime
:有些瀏覽器實現爲navigationStart
,表明瀏覽器開始unload前一個頁面文檔的開始時間節點。好比咱們當前正在瀏覽baidu.com,在地址欄輸入google.com並回車,瀏覽器的執行動做依次爲:unload當前文檔(即baidu.com)->請求下一文檔(即google.com)。navigationStart的值即是觸發unload當前文檔的時間節點。數組
若是當前文檔爲空,則navigationStart的值等於fetchStart。瀏覽器
redirectStart
和redirectEnd
:若是頁面是由redirect而來,則redirectStart和redirectEnd分別表明redirect開始和結束的時間節點;unloadEventStart
和unloadEventEnd
:若是前一個文檔和請求的文檔是同一個域的,則unloadEventStart
和unloadEventEnd
分別表明瀏覽器unload前一個文檔的開始和結束時間節點。不然二者都等於0;fetchStart
是指在瀏覽器發起任何請求以前的時間值。在fetchStart和domainLookupStart
之間,瀏覽器會檢查當前文檔的緩存;domainLookupStart
和domainLookupEnd
分別表明DNS查詢的開始和結束時間節點。若是瀏覽器沒有進行DNS查詢(好比使用了cache),則二者的值都等於fetchStart
;connectStart
和connectEnd
分別表明TCP創建鏈接和鏈接成功的時間節點。若是瀏覽器沒有進行TCP鏈接(好比使用持久化鏈接webscoket),則二者都等於domainLookupEnd
;secureConnectionStart
:可選。若是頁面使用HTTPS,它的值是安全鏈接握手以前的時刻。若是該屬性不可用,則返回undefined。若是該屬性可用,但沒有使用HTTPS,則返回0;requestStart
表明瀏覽器發起請求的時間節點,請求的方式能夠是請求服務器、緩存、本地資源等;responseStart
和responseEnd
分別表明瀏覽器收到從服務器端(或緩存、本地資源)響應回的第一個字節和最後一個字節數據的時刻;domLoading
表明瀏覽器開始解析html文檔的時間節點。咱們知道IE瀏覽器下的document有readyState
屬性,domLoading
的值就等於readyState
改變爲loading
的時間節點;domInteractive
表明瀏覽器解析html文檔的狀態爲interactive
時的時間節點。domInteractive
並不是DOMReady,它早於DOMReady觸發,表明html文檔解析完畢(即dom tree建立完成)可是內嵌資源(好比外鏈css、js等)還未加載的時間點;domContentLoadedEventStart
:表明DOMContentLoaded
事件觸發的時間節點:緩存
頁面文檔徹底加載並解析完畢以後,會觸發DOMContentLoaded事件,HTML文檔不會等待樣式文件,圖片文件,子框架頁面的加載(load事件能夠用來檢測HTML頁面是否徹底加載完畢(fully-loaded))。
domContentLoadedEventEnd
:表明DOMContentLoaded
事件完成的時間節點,此刻用戶能夠對頁面進行操做,也就是jQuery中的domready時間;domComplete
:html文檔徹底解析完畢的時間節點;loadEventStart
和loadEventEnd
分別表明onload事件觸發和結束的時間節點
2.2.2 計算性能指標
可使用Navigation.timing
統計到的時間數據來計算一些頁面性能指標,好比DNS查詢耗時、白屏時間、domready等等。以下:
因此根據上面的時間點,咱們能夠計算常規的性能值,以下:
(使用該api時須要在頁面徹底加載完成以後才能使用,最簡單的辦法是在window.onload事件中讀取各類數據,由於不少值必須在頁面徹底加載以後才能得出。)
var timing = window.performance && window.performance.timing;
var navigation = window.performance && window.performance.navigation;
重定向次數:
var redirectCount = navigation && navigation.redirectCount;
跳轉耗時:
var redirect = timing.redirectEnd - timing.redirectStart;
APP CACHE 耗時:
var appcache = Math.max(timing.domainLookupStart - timing.fetchStart, 0);
DNS 解析耗時:
var dns = timing.domainLookupEnd - timing.domainLookupStart;
TCP 連接耗時:
var conn = timing.connectEnd - timing.connectStart;
等待服務器響應耗時(注意是否存在cache):
var request = timing.responseStart - timing.requestStart;
內容加載耗時(注意是否存在cache):
var response = timing.responseEnd - timing.responseStart;
整體網絡交互耗時,即開始跳轉到服務器資源下載完成:
var network = timing.responseEnd - timing.navigationStart;
渲染處理:
var processing = (timing.domComplete || timing.domLoading) - timing.domLoading;
拋出 load 事件:
var load = timing.loadEventEnd - timing.loadEventStart;
總耗時:
var total = (timing.loadEventEnd || timing.loadEventStart || timing.domComplete || timing.domLoading) - timing.navigationStart;
可交互:
var active = timing.domInteractive - timing.navigationStart;
請求響應耗時,即 T0,注意cache:
var t0 = timing.responseStart - timing.navigationStart;
首次出現內容,即 T1:
var t1 = timing.domLoading - timing.navigationStart;
內容加載完畢,即 T3:
var t3 = timing.loadEventEnd - timing.navigationStart;
複製代碼
2.2.3 Resource timing API
Resource timing API是用來統計靜態資源相關的時間信息,詳細的內容請參考W3C Resource timing。這裏咱們只介紹performance.getEntries
方法,它能夠獲取頁面中每一個靜態資源的請求,【以百度移動版首頁的logo爲例】以下:
能夠看到performance.getEntries
返回一個數組,數組的每一個元素表明對應的靜態資源的信息,好比上圖展現的第一個元素對應的資源類型initiatorType
是圖片img
,請求花費的時間就是duration
的值。
關於Resource timing API的使用場景,感興趣的同窗能夠深刻研究。
;
(function() {
handleAddListener('load', getTiming)
function handleAddListener(type, fn) {
if(window.addEventListener) {
window.addEventListener(type, fn)
} else {
window.attachEvent('on' + type, fn)
}
}
function getTiming() {
try {
var time = performance.timing;
var timingObj = {};
var loadTime = (time.loadEventEnd - time.loadEventStart) / 1000;
if(loadTime < 0) {
setTimeout(function() {
getTiming();
}, 200);
return;
}
timingObj['重定向時間'] = (time.redirectEnd - time.redirectStart) / 1000;
timingObj['DNS解析時間'] = (time.domainLookupEnd - time.domainLookupStart) / 1000;
timingObj['TCP完成握手時間'] = (time.connectEnd - time.connectStart) / 1000;
timingObj['HTTP請求響應完成時間'] = (time.responseEnd - time.requestStart) / 1000;
timingObj['DOM開始加載前所花費時間'] = (time.responseEnd - time.navigationStart) / 1000;
timingObj['DOM加載完成時間'] = (time.domComplete - time.domLoading) / 1000;
timingObj['DOM結構解析完成時間'] = (time.domInteractive - time.domLoading) / 1000;
timingObj['腳本加載時間'] = (time.domContentLoadedEventEnd - time.domContentLoadedEventStart) / 1000;
timingObj['onload事件時間'] = (time.loadEventEnd - time.loadEventStart) / 1000;
timingObj['頁面徹底加載時間'] = (timingObj['重定向時間'] + timingObj['DNS解析時間'] + timingObj['TCP完成握手時間'] + timingObj['HTTP請求響應完成時間'] + timingObj['DOM結構解析完成時間'] + timingObj['DOM加載完成時間']);
for(item in timingObj) {
console.log(item + ":" + timingObj[item] + '毫秒(ms)');
}
console.log(performance.timing);
} catch(e) {
console.log(timingObj)
console.log(performance.timing);
}
}
})();
複製代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="//cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" />
<script src=""></script>
<script type="text/javascript" src=""></script>
</head>
<body>
</body>
</html>
複製代碼