前面的話
頁面性能一直都是Web開發人員比較關注的領域。但在實際應用中,度量頁面性能的指標,是javascript的Date對象。Web Timing API改變了這個局面,讓開發人員通過javascript就能使用瀏覽器內部的度量結果,給出了頁面加載和渲染過程的很多信息,對性能優化非常有價值。本文將詳細介紹web Timing API——performance對象
簡述
Web計時機制的核心是window.performance對象。對頁面的所有度量信息,包括那些規范中已經定義的和將來才能確定的,都包含在這個對象里面。performance對象包括navigation和timing對象,以及chrome擴展的memory對象,還包括getEntries()和now()兩個方法
值得高興的是,低版本IE也支持performance對象

memory
memory屬性是chrome擴展的對象,只有chrome瀏覽器支持,包含以下三個屬性:
jsHeapSizeLimit表示內存大小限制
totalJSHeapSize表示可使用的內存
usedJSHeapSize表示javascript對象占用的內存
/* jsHeapSizeLimit: 793000000 totalJSHeapSize: 10000000 usedJSHeapSize: 10000000 */ console.log(performance.memory);
navigation
performance.navigation屬性是一個對象,包含着與頁面導航有關的redirectCount和type這兩個屬性
其中redirectCount表示頁面加載前的重定向次數;而type是一個數值常量,表示剛剛發生的導航類型,type有以下取值
performance.navigation.TYPE_NAVTGATE(0):頁面第一次加載 performance.navigation.TYPE_RELOAD(1):頁面重載過 performance.navigation.TYPE_BACK_FORWARD(2):頁面是通過“后退”或“前進”按鈕打開的
console.log(window.performance.navigation.redirectCount);//0 console.log(window.performance.navigation.type);//1
timing
performance.timing屬性也是一個對象,但這個對象的屬性都是時間戳,不同的事件會產生不同的時間值
下圖顯示了一個請求發出的整個過程中,各種環節的時間順序
下面按照時間順序對timing對象的各個屬性進行說明
navigationStart:開始導航到當前頁面的時間,即在地址欄輸入地址后按下回車時的時間
var navigationStart = performance.timing.navigationStart; //1488984540668 console.log(navigationStart); //Wed Mar 08 2017 22:49:44 GMT+0800 (中國標准時間) console.log(new Date(new Date(navigationStart)));
redirectStart:到當前頁面的重定向開始的時間。但只有在重定向的頁面來自同一個域時這個屬性才會有值;否則,值為0
redirectEnd:到當前頁面的重定向結束的時間。但只有在重定向的頁面來自同一個域時這個屬性才會有值;否則,值為0
console.log(performance.timing.redirectStart);//0 console.log(performance.timing.redirectEnd);//0
fetchStart:開始通過HTTP GET取得頁面的時間
console.log(performance.timing.fetchStart);//1488984540668
domainLookupStart:開始査詢當前頁面DNS的時間,如果使用了本地緩存或持久連接,則與fetchStart值相等
domainLookupEnd:査詢當前頁面DNS結束的時間,如果使用了本地緩存或持久連接,則與fetchStart值相等
console.log(performance.timing.domainLookupStart);//1488984540670 console.log(performance.timing.domainLookupEnd);//1488984540671
connectStart:瀏覽器嘗試連接服務器的時間
secureConnectionStart:瀏覽器嘗試以SSL方式連接服務器的時間。不使用SSL方式連接時,這個屬性的值為0
connectEnd:瀏覽器成功連接到服務器的時間
console.log(performance.timing.connectStart);//1488984540671 console.log(performance.timing.secureConnectionStart);//0 console.log(performance.timing.connectEnd);//1488984540719
requestStart:瀏覽器開始請求頁面的時間
responseStart:瀏覽器接收到頁面第一字節的時間
responseEnd:瀏覽器接收到頁面所有內容的時間
console.log(performance.timing.requestStart);//1488984540720 console.log(performance.timing.responseStart);//1488984540901 console.log(performance.timing.responseEnd);//1488984540902
unloadEventStart:前一個頁面的unload事件開始的時間。但只有在前一個頁面與當前頁面來自同一個域時這個屬性才會有值;否則,值為0
unloadEventEnd:前一個頁面的unload事件結束的時間。但只有在前一個頁面與當前頁面來自同一個域時這個屬性才會有值;否則,值為0
console.log(performance.timing.unloadEventStart);//1488984540902 console.log(performance.timing.unloadEventEnd);//1488984540903
domLoading:document.readyState變為"loading"的時間,即開始解析DOM樹的時間
domInteractive:document.readyState變為"interactive"的時間,即完成完成解析DOM樹的時間
domContentLoadedEventStart:發生DOMContentloaded事件的時間,即開始加載網頁內資源的時間
domContentLoadedEventEnd:DOMContentLoaded事件已經發生且執行完所有事件處理程序的時間,網頁內資源加載完成的時間
domComplete:document.readyState變為"complete"的時間,即DOM樹解析完成、網頁內資源准備就緒的時間
console.log(performance.timing.domLoading);//1488984540905 console.log(performance.timing.domInteractive);//1488984540932 console.log(performance.timing.domContentLoadedEventStart);//1488984540932 console.log(performance.timing.domContentLoadedEventEnd);//1488984540932 console.log(performance.timing.domComplete);//1488984540932
loadEventStart:發生load事件的時間,也就是load回調函數開始執行的時間
loadEventEnd:load事件已經發生且執行完所有事件處理程序的時間
console.log(performance.timing.loadEventStart);//1488984540933 console.log(performance.timing.loadEventEnd);//1488984540933
[注意]在實際情況下,通過performance.timing屬性可以找到domInteractive、domContentLoadedEventStart、domContentLoadedEventEnd、domComplete、loadEventStart和loadEventEnd這6個值。但是在單獨獲取的情況下,這6個值都為0
/* connectEnd:1488989686331 connectStart:1488989686330 domComplete:1488989686395 domContentLoadedEventEnd:1488989686395 domContentLoadedEventStart:1488989686393 domInteractive:1488989686393 domLoading:1488989686336 domainLookupEnd:1488989686330 domainLookupStart:1488989686330 fetchStart:1488989686328 loadEventEnd:1488989686395 loadEventStart:1488989686395 navigationStart:1488989686328 redirectEnd:0 redirectStart:0 requestStart:1488989686331 responseEnd:1488989686333 responseStart:1488989686332 secureConnectionStart:0 unloadEventEnd:1488989686333 unloadEventStart:1488989686333 */ console.log(performance.timing);
/* navigationStart:1488989686328 unloadEventStart:1488989686333 unloadEventEnd:1488989686333 redirectStart:0 redirectEnd:0 fetchStart:1488989686328 domainLookupStart:1488989686330 domainLookupEnd:1488989686330 connectStart:1488989686330 connectEnd:1488989686331 secureConnectionStart:0 requestStart:1488989686331 responseStart:1488989686332 responseEnd:1488989686333 domLoading:1488989686336 domInteractive:0 domContentLoadedEventStart:0 domContentLoadedEventEnd:0 domComplete:0 loadEventStart:0 loadEventEnd:0 */ var timing = performance.timing; for(var value in timing){ console.log(value + ':'+timing[value]); }
getEntries()
getEntries()方法將返回一個數組,包含了頁面中所有的HTTP資源請求
[注意]IE8-瀏覽器不支持
以下面的頁面為例,可知頁面有jquery一個資源的請求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script> <script> console.log(performance.getEntries()); </script> </body> </html>
結果如下圖所示,由於只有一個資源,所以該資源處於performance.getEntries()[0]中
其中,duration表示加載時間;name表示資源的絕對路徑;entryType表示資源類型;initiatorType表示發起請求的標簽
now()
now()方法返回從頁面初始化到調用該方法時的毫秒數
[注意]IE9-瀏覽器不支持
performance.now()與Date.now()不同的是,返回了以微秒為單位的時間,更加精准
並且與Date.now()會受系統程序執行阻塞的影響不同,performance.now()的時間是以恆定速率遞增的,不受系統時間的影響(系統時間可被人為或軟件調整)
Date.now()輸出的是UNIX時間,即距離1970年1月1日0點的時間,而performance.now()輸出的是相對於performance.timing.navigationStart(頁面初始化)的時間
var t0 = window.performance.now(); doSomething(); var t1 = window.performance.now(); console.log("doSomething函數執行了" + (t1 - t0) + "毫秒.")
性能指標
通過timing屬性的這些時間值,就可以全面了解頁面在被加載到瀏覽器的過程中都經歷了哪些階段,而哪些階段可能是影響性能的瓶頸
【重定向時間】
times.redirect = timing.redirectEnd - timing.redirectStart; console.log(times.redirect);//0
【DNS查詢時間】
times.lookupDomain = timing.domainLookupEnd - timing.domainLookupStart; console.log(times.lookupDomain);//1
【TCP握手時間】
times.connect = timing.connectEnd - timing.connectStart; console.log(times.connect);//48
【HTTP響應時間】
通過瀏覽器發出HTTP請求,到瀏覽器接受完HTTP響應的時間
times.request = timing.responseEnd - timing.requestStart; console.log(times.request);//182
最終,性能指標對象times表示如下
var timing = performance.timing; var times = { redirect:timing.redirectEnd - timing.redirectStart, lookupDomain:timing.domainLookupEnd - timing.domainLookupStart, connect:timing.connectEnd - timing.connectStart, request:timing.responseEnd - timing.requestStart };