HTML5提供的performance接口精確的告訴我們當訪問一個網站頁面時當前網頁每個處理階段的精確時間(timestamp),以方便我們進行前端分析。
它是瀏覽器的直接實現,比在網頁中用js設置Date.time或者cookie來分析網頁時間上要精確很多。
支持瀏覽器: IE9+,Chrome11+,Firefox7+.
以下是w3c提供的performance.timing各階段api圖
成員:
.navigation (一個叫做performanceNavigation的對象.)
.timing (這是一個被稱作performanceTiming的包含了很多成員的對象)
PS:
1. performance,僅能對當前的html文檔做檢測,所有的對象都和當前文檔有關。如果我們想檢測某個圖片資源的網絡狀況,則不行。 比如我們想監控,用戶訪問我們服務的狀況,就只能創建一個iframe,url為我們服務某個地址(除非用戶訪問的當前頁,就是我們要監控的對象)。然后才可以監控這次一次請求的網絡狀態等等。所以建議如果可以考慮使用performance做監控,則需要有抽樣、時間點等監控機制。否則給服務器帶來額外壓力,得不償失。如果要監控其他資源,需要使用 ResourceTiming。
performanceNavigation(performance.navigation)對象的成員
performanceNavigation.type
返回值應該是0,1,2 中的一個.分別對應三個枚舉值:
0 : TYPE_NAVIGATE (用戶通過常規導航方式訪問頁面,比如點一個鏈接,或者一般的get方式.)
1 : TYPE_RELOAD (用戶通過刷新,包括JS調用刷新接口等方式訪問頁面)
2 : TYPE_BACK_FORWARD (用戶通過后退按鈕訪問本頁面)
ps:草案中其實還有 3 : TYPE_RESERVED (保留,其他非前三種方式訪問.)
performanceNavigation.redirectCount
一個只讀屬性,返回當前頁面是幾次重定向才過來的。但是這個接口有同源策略限制,即僅能檢測同源的重定向。
bugs:
1. IE9,當一個同源的頁面a連接到地址b(是否於a,c同源都如此),后被重定向到同源頁面c時,navigation.redirectCount居然會是1。而不是0,此bug已被IE10 PP2修復。
performanceTiming(performance.timing)對象的成員:
.navigationStart
瀏覽器完成卸載前一個文檔的時間(也就是准備加載新頁面的那個起始時間)。如果沒有前一個文檔,那么就返回 timing.fetchStart的值。
似乎只有Chrome 非常嚴格遵守了此草案。 即不把刷新頁面,以及一個標簽頁輸入地址到指定頁面,視為發生文檔的卸載。
bugs:
1. IE9,當發生重定向時,.navigationStart 會是0。IE10 PP2 已修復此問題.
2. IE9-IE10 PP2,的一個問題是刷新當前頁面,或在某個標簽頁輸入地址為非相同頁面時,會被視為存在前一個文檔,也就是說,其navigationStart會早於fetchStart。(除非在當前頁再次輸入地址按回車。再次進入該頁面,則被視為無前一個文檔被卸載)。而實際上這時候navigationStart,是unloadEventEnd的時間。
3. Firefox7-Firefox10,一個新標簽頁也會被視為一個有效的文檔。所以這時候,會有值,且不是fetchStart的值。
.unloadEventStart
如果前一個文檔,和當前文檔同源,返回前一個文檔發生unload事件前的時間.如果沒有前一個文檔,或不同源,則返回0.
bugs:
1. IE9-IE10 pp2,Chrome17-,在前一個文檔與當前文檔中間發生重定向時, 且前后兩個文檔同源時, unloadEventStart,也會返回0
.unloadEventEnd
如果前一個文檔和當前文檔同源.返回前一個文檔發生unload事件的時間. 如果沒有前一個文檔,或不同源,則返回0。
如果,發生了HTTP重定向,或者類似的事情。並且,從導航開始中間的每次重定向,並不都和當前文檔同域的話,則返回0。
bugs:
1. IE9-IE10 pp2,Chrome17-,在前一個文檔與當前文檔中間發生重定向時,且前后兩個文檔同源時,unloadEventEnd也會返回0。
.redirectStart
如果,發生了HTTP重定向,或者類似的事情。並且,從導航開始,中間的每次重定向,都和當前文檔同域的話,就返回開始重定向的,timing.fetchStart的值。其他情況,則返回0。
bugs:
1. IE9-IE10 pp2,在頁面a,鏈接到地址b,並重定向到與b同源的頁面c時。redirectStart,將為0.即同源策略,居然會考慮導航頁。
.redirectEnd
如果,發生了HTTP重定向,或者類似的事情.並且,從導航開始,中間的每次重定向,都和當前文檔同域的話,就返回最后一次重定向,接收到最后一個字節數據后的那個時間.其他情況則返回0.
bugs:
1. IE9-IE10 pp2,在頁面a,鏈接到地址b,並重定向到與b同源的頁面c時. redirectSEnd,將為0.即同源策略,居然會考慮導航頁.
.fetchStart
如果一個新的資源(這里是指當前文檔)獲取被發起,或類似的事情發生,則 fetchStart必須返回用戶代理開始檢查其相關緩存的那個時間,其他情況則返回開始獲取該資源的時間.
.domainLookupStart
返回用戶代理對當前文檔所屬域進行DNS查詢開始的時間. 如果此請求沒有DNS查詢過程,如長連接,資源cache,甚至是本地資源等. 那么就返回 fetchStart的值.
bugs:
1. Firefox7-Firefox10,的實現有錯誤. 因為其值,並沒有遵守標准所描述的對應時間節點.而是默認以navigationStart作為時間起點,並以中間的重定向時間做累加.而得到domainLookupStart的時間.即使這個重定向是非同源的重定向.所消耗的時間都會被計算進去. 那么,這也就解釋了,為什么當沒有重定向發生時, domainLookupStart - fetchStart, 我們往往會得到一個負值的原因,因為navigationStart,是要早於 fetchStart的.
.domainLookupEnd
返回用戶代理對結束對當前文檔所屬域進行DNS查詢的時間.如果此請求沒有DNS查詢過程,如長連接,資源cache,甚至是本地資源等. 那么就返回 fetchStart的值.
bugs:
1.參考domainLookupStart的bug. End具備相同的問題.
.connectStart
返回用戶代理向服務器服務器請求文檔,開始建立連接的那個時間,如果此連接是一個長連接,又或者直接從緩存中獲取資源(即沒有與服務器建立連接).則返回domainLookupEnd的值.
bugs:
1. Firefox7 當資源走cache,即並未創建連接時. connentStart 的值為0.
2. Firefox8-Firefox10,當並未創建連接時,connetStart的值是fetchStart的值,而不是domainLookEnd的值. 但這里涉及到一個慣性問題,因為domainLookupEnd的累積時間就已經背離了標准了,所以即使connectStart遵守標准.也是一個有問題的值.
.connectEnd
返回用戶代理向服務器服務器請求文檔,建立連接成功后(注意,不是斷開連接的時間.)的那個時間.如果此連接是一個長連接,又或直接從緩存中獲取資源 (即沒有與服務器建立連接),則返回domainLookupEnd的值.
bugs:
參考connectStart的問題.connectEnd具備同樣的問題.
如果連接建立失敗,而用戶代理進行重連,則connectStart和connectEnd則應該是這次重連的相關的值.其中connectEnd必須包括建立連接的時間以及,SSH握手協議和SOCKS認證等時間.
.secureConnectionStart
可選特性.用戶代理如果沒有對應的東東,就要把這個設置為undefined.如果有這個東東,並且是HTTPS協議,那么就要返回開始SSL握手的那個時間. 如果不是HTTPS, 那么就返回0.
補充:Firefox7-10,IE9-IE10 PP2,都木有實現這個api.所以始終是undefined.
.requestStart
返回從服務器、緩存、本地資源等,開始請求文檔的時間.
如果請求中途,連接斷開了,並且用戶代理進行了重連,並重新請求了資源,那么requestStart就必須為這個新請求所對應的時間.
performance.timing 並不包含一個 單表請求結束的"requestEnd"接口. 原因有兩點:
1. 用戶代理所能確定的請求的結束,並不能代表正確的網絡栓書中的結束時間. 所以設計這個屬性並沒什么用處.
2. 一些用戶代理,如果要封裝一個代表HTTP層面的,請求結束時間的接口,成本會非常高昂.
.responseStart
返回用戶代理從服務器、緩存、本地資源中,接收到第一個字節數據的時間.
.responseEnd
返回用戶代理接收到最后一個字符的時間,和當前連接被關閉的時間中,更早的那個. 同樣,文檔可能來自服務器、緩存、或本地資源.
補充: 此值的讀取應該是在我們可以確保真的是Response結束以后. 比如window.onload. 因為考慮到chunked輸出的情況. 那么我們腳本執行,並獲取該值時,響應還沒有結束. 這就會導致獲取時間不准確.
.domLoading
返回用戶代理把其文檔的 "current document readiness" 設置為 "loading"的時候.
(current document readiness 其實就是document.readyState API對應的狀態.)
參考:http://dev.w3.org/html5/spec/dom.html#current-document-readiness
.domInteractive
返回用戶代理把其文檔的 "current document readiness" 設置為 "interactive"的時候.
從標准來說,domReady的狀態為"interactive"時,意味着,文檔解析結束了. 因為標准中描述, DOM樹創建結束后第一件事,就是把 "current document readiness" 設置為"interactive"
參考:http://dev.w3.org/html5/spec/the-end.html#the-end 中第一步.
.domContentLoadedEventStart
返回文檔發生 DOMContentLoaded事件的時間.
.domContentLoadedEventEnd
文檔的DOMContentLoaded 事件的結束時間.
補充:所謂事件結束的時間,是指,如果DOMContentLoaded事件被開發者注冊了回調事件.那么這個時間的End時間減去Start的時間.就會是這個回調執行的大概事件. 當然居於部分瀏覽器實現可能會有2-3ms的誤差. 但是這個時間,基本可以忽略不計. 類似的情況還有后面的.loadEventStart,End. 即 window.onload 所有回調所消耗的時間.
.domComplete
返回用戶代理把其文檔的 "current document readiness" 設置為 "complete"的時候.
PS:如果 current document readiness 的某個狀態被多次觸發,那么對應的 domLoading, domInteractive, domContentLoadedEventStart, domContentLoadedEventEnd and domComplete這些對應的API返回的時間,就應該是這個狀態第一次觸發的時間.
.loadEventStart
文檔觸發load事件的時間. 如果load事件沒有觸發,那么該接口就返回0.
.loadEventEnd
文檔觸發load事件結束后的時間. 如果load事件沒有觸發,那么該接口就返回0.
external : 另外,我很期待微軟的私有實現,msFirstPaint 的屬性。能夠得到標准的采納...這樣對於監控瀏覽器首次渲染花費的時間.有太重大的意義了。
Chrome 也有了一些私有支持:
var timing = performance.timing; var readyStart = timing.fetchStart - timing.navigationStart; var redirectTime = timing.redirectEnd - timing.redirectStart; var appcacheTime = timing.domainLookupStart - timing.fetchStart; var unloadEventTime = timing.unloadEventEnd - timing.unloadEventStart; var lookupDomainTime = timing.domainLookupEnd - timing.domainLookupStart; var connectTime = timing.connectEnd - timing.connectStart; var requestTime = timing.responseEnd - timing.requestStart; var initDomTreeTime = timing.domInteractive - timing.responseEnd; var domReadyTime = timing.domComplete - timing.domInteractive; //過早獲取時,domComplete有時會是0 var loadEventTime = timing.loadEventEnd - timing.loadEventStart; var loadTime = timing.loadEventEnd - timing.navigationStart;//過早獲取時,loadEventEnd有時會是0 console.log('准備新頁面時間耗時: ' + readyStart); console.log('redirect 重定向耗時: ' + redirectTime); console.log('Appcache 耗時: ' + appcacheTime); console.log('unload 前文檔耗時: ' + unloadEventTime); console.log('DNS 查詢耗時: ' + lookupDomainTime); console.log('TCP連接耗時: ' + connectTime); console.log('request請求耗時: ' + requestTime); console.log('請求完畢至DOM加載: ' + initDomTreeTime); console.log('解釋dom樹耗時: ' + domReadyTime); console.log('load事件耗時: ' + loadEventTime); console.log('從開始至load總耗時: ' + loadTime);
摘自:
http://www.cnblogs.com/_franky/archive/2011/11/07/2238980.html