使用window.performance分析web前端性能

說在前面javascript

最近身體出了點問題,折騰了個把星期總算活過來。差很少個把星期沒寫博客了,今天分享一個比較好玩的東東—performancehtml

上一篇博客中分享了不少頁面性能的測試工具,一般,頁面的性能問題也是咱們開發中一個重要環節,但一直以來咱們也沒有沒有比較好的手段,來檢測頁面的性能;一般,咱們只能以來與chrome或者FF瀏覽器自帶的profiletimming或者使用在線的pagetest,阿里測等。咱們很但願有一套頁面性能的api,咱們能夠本身編寫代碼測試頁面性能而不須要藉助於其餘的工具。java

好在W3C Web性能工做小組已經git

與各瀏覽器廠商都已認識到性能對於web開發的重要性,爲了解決當前性能測試的困難,W3C推出了一套性能API標準,各類瀏覽器對這套標準的支持現在也逐漸成熟起來。這套API的目的是簡化開發者對網站性能進行精確分析與控制的過程,方便開發者採起手段提升web性能。
github


正文web

整套標準包含了10餘種API,各自針對性能檢測的某個方面。在下圖中能夠看到它們當前在規範流程中的進展:chrome

wKioL1ZcSTXiPaqbAACkT1e8UQg360.png


下面是API描述的功能列表
segmentfault


wKiom1ZcSW3B0mRnAAWjIzkO6x8472.jpg


瀏覽器支持狀況
api

wKiom1ZcSfaAialBAAJmZgOoup4070.jpg

有兩個使咱們必需要關注的:數組

1.     頁面加載Navigation Timing

2.     頁面資源加載Timing: Resource Timing

這兩個API很是有用,能夠幫助咱們獲取頁面的Domready時間、onload時間、白屏時間等,以及單個頁面資源在從發送請求到獲取到rsponse各階段的性能參數。

使用這兩個API時須要在頁面徹底加載完成以後才能使用,最簡單的辦法是在window.onload事件中讀取各類數據,由於不少值必須在頁面徹底加載以後才能得出。


(1)頁面加載Navigation Timing

    該對象可以幫助網站開發者檢測真實用戶數據(RUM),例如帶寬、延遲或主頁的總體頁面加載時間。

打開chrome瀏覽器輸入:performance.timing;以下圖所示

wKiom1ZcSpmguSzrAAKxHjnHb-U768.jpg

返回了一個返回的是一個PerformanceTiming對象,包含了各類與瀏覽器性能有關的時間數據,提供瀏覽器處理網頁各個階段的耗時,它包含的頁面性能屬性以下表:

wKiom1ZcTF2CG3WzAAd0uSIn4aM329.jpg

下面有一個圖,能更加直觀的展現,這些數據直接的關係。

wKioL1ZcTOOArNNrAABqmp7zgc8825.png

對咱們比較有用的頁面性能數據大概包括以下幾個:

DNS查詢耗時、TCP連接耗時、request請求耗時、解析dom樹耗時、白屏時間、domready時間、onload時間等,而這些參數是經過上面的performance.timing各個屬性的差值組成的,計算方法以下:

DNS查詢耗時 domainLookupEnd - domainLookupStart

TCP連接耗時 connectEnd - connectStart

request請求耗時 responseEnd - responseStart

解析dom樹耗時 domComplete- domInteractive

白屏時間 responseStart - navigationStart

domready時間 domContentLoadedEventEnd - navigationStart

onload時間 loadEventEnd - navigationStart

NavigationTiming的目的是用於分析頁面總體性能指標。若是要獲取個別資源(例如JS、圖片)的性能指標,就須要使用Resource Timing API


Resource Timing API

這個主要用來獲取到單個靜態資源(Js,CSS,圖片,音頻視頻等等)從開始發出請求到獲取響應之間各個階段的Timing

同理在chrome的console輸入performance.getEntries();顯示了全部靜態資源的數組列表;點開後顯示了,某一個請求的相關參數有name,type,時間等等。

wKiom1ZcTPKANgZOAAKDheEoLnQ143.jpg

這個接口是獲取全部的資源;同時,該API還提供了另外另個接口

performance.getEntriesByName()
performance.getEntriesByType()

顧名思義,分別是按資源的名稱和類型獲取相應的請求數據。


memory:瀏覽器內存狀況

同理輸入performance.memory

wKioL1ZcTv-wN7zcAABvTtHebW4704.jpg

  1. jsHeapSizeLimit

  2. totalJSHeapSize

  3. usedJSHeapSize    

    注:usedJSHeapSize表示全部被使用的js堆棧內存;totalJSHeapSize表示當前js堆棧內存總大小,這表示usedJSHeapSize不能大於totalJSHeapSize,若是大於,有可能出現了內存泄漏



performance.navigation對象

performance還能夠提供一些用戶行爲信息,主要都存放在performance.navigation對象上面。

chrome下以下圖:

wKioL1ZcT-ji-vIvAAEzP5CJrvA246.jpg

這個對象有兩個屬性:

1performance.navigation.type

該屬性返回一個整數值,表示網頁的加載來源,可能有如下4種狀況:

0:網頁經過點擊連接、地址欄輸入、表單提交、腳本操做等方式加載,至關於常                        數performance.navigation.TYPE_NAVIGATENEXT

1:網頁經過從新加載按鈕或者location.reload()方法加載,至關於常                       數performance.navigation.TYPE_RELOAD

2:網頁經過前進後退按鈕加載,至關於常         數performance.navigation.TYPE_BACK_FORWARD

255:任何其餘來源的加載,至關於常數performance.navigation.TYPE_UNDEFINED

2performance.navigation.redirectCount

表示當前網頁通過了多少次重定向跳轉。


最後呢,本身寫了一段js來測試了上面的相關參數,代碼以下:

(function(w){
	var resultObj = {};
	//初始化相關
	function TestTiming(timing){
		var timerArr = [];
		var dnsTimer = {key:"DNS查詢耗時" , value:timing.domainLookupEnd - timing.domainLookupStart + "ms"};
		var tcpTimer = {key:"TCP連接耗時" , value:timing.connectEnd - timing.connectStart + "ms"};
		var requestTimer = {key:"request請求耗時" , value:timing.responseEnd - timing.responseStart + "ms"};
		var domTimer = {key:"解析dom樹耗時" , value:timing.domComplete - timing.domInteractive + "ms"};
		var pageEmptyTimer = {key:"白屏時間" , value:timing.responseStart - timing.navigationStart + "ms"};
		var domReadyTimer = {key:"domready時間" , value:timing.domContentLoadedEventEnd - timing.navigationStart + "ms"};
		var onloadTimer = {key:"onload時間" , value:timing.loadEventEnd - timing.navigationStart + "ms"};

		timerArr = timerArr.concat(dnsTimer, tcpTimer, requestTimer, domTimer, pageEmptyTimer, domReadyTimer, onloadTimer);
		return timerArr;
	}
	//請求的各類資源(js,圖片,樣式等)
	function TestResource(resourcesObj){
		var resourceArr = [];
		var len = resourcesObj.length;
		for(var i = len - 1;i >0;i--){
			var temp = {};
			var cur = resourcesObj[i];
			temp.key = cur.name;
			temp.resValue = cur.responseEnd - cur.requestStart + "ms";
			temp.conValue = cur.connectEnd - cur.connectStart + "ms";
			resourceArr.push(temp);
		}
		return resourceArr;
	}
	//頁面的加載方式
	function pageLoadMethod(type){
		var arr = [];
		var loadMethod = {};
		loadMethod.name = "進入頁面的方式";
		var str = "";
		switch(type){
			case 0:
				str = '點擊連接、地址欄輸入、表單提交、腳本操做等方式加載';
				break;
			case 1:
				str = '經過「從新加載」按鈕或者location.reload()方法加載';
				break;
			case 2:
				str = '網頁經過「前進」或「後退」按鈕加載';
				break;
			default:
				str = '任何其餘來源的加載';
				break;
		}
		loadMethod.value = str;
		arr.push(loadMethod);
		return arr;
	}
	//輸出性能數據
	function outPutData(perObj){
		var timerArr = TestTiming(perObj.timing);
		var resourcesArr = TestResource(perObj.getEntries());
		var loadMethodArr = pageLoadMethod(perObj.navigation.type);
		console.log("-------頁面初始化------------------------");
		console.table(timerArr);
		console.log("-------頁面請求------------------------");
		console.table(resourcesArr);
		console.log("-------頁面加載方式------------------------");
		console.table(loadMethodArr);
	}

	w.perTestResult = outPutData;
})(window);

說在最後

相關資料

1  http://segmentfault.com/a/1190000004010453

2  https://github.com/fredshare/blog/issues/5

3  http://javascript.ruanyifeng.com/bom/performance.html#toc5

相關文章
相關標籤/搜索