經常會看些性能分析的書,但是實際在做優化的時候又無從下手。
因為沒有數據,也不能確定實際用戶到底在哪一環影響了他們的性能。
現在H5提供了一些很方便的Performance接口,可以讓我們更方便的搜集到用戶的數據,不過有幾個方法的兼容性實在太差。
插件已經上傳到Github中,可以在這里獲取到,index.html中寫的是一些示例,插件源碼在“js/primus.js”中。
寫的比較倉促,自己能力也有限,如有問題,歡迎指正。
一、請求時間統計
上圖是performance.timing監測到的特定於用戶的計時器,通過這些屬性的組合搭配,可以獲取到特定的時間數據。
垂直角度的度量順序圖:
1)performance
設置好插件中全局的performance對象,以及方法now,獲取當前時間戳。
2)Document.readyState
上圖中的“domComplete”、“domInteractive”和“domLoading”,就是Document。readyState的3種狀態loading, interactive或complete發生的時間。
3)getTimes()
在這個方法中計算各個參數之間的值。
在網上參考了很多資料,再結合了一點自己的理解,有些參數的理解可能有誤,具體的計算方式可以查看源碼“primus.js”。
1. firstPaint:白屏時間,也就是開始解析DOM耗時,用戶在沒有滾動時候看到的內容渲染完成並且可以交互的時間
2. loadTime:加載總時間,這幾乎代表了用戶等待頁面可用的時間
3. unloadEventTime:Unload事件耗時
4. loadEventTime:執行 onload 回調函數的時間
5. domReadyTime:用戶可操作時間
6. firstScreen:首屏時間,用戶在沒有滾動時候看到的內容渲染完成並且可以交互的時間,記錄載入時間最長的圖片
7. parseDomTime:解析 DOM 樹結構的時間,期間要加載內嵌資源
8. initDomTreeTime:請求完畢至DOM加載耗時
9. readyStart:准備新頁面時間耗時
10. redirectTime:重定向的時間
11. appcacheTime:DNS緩存耗時
12. lookupDomainTime:DNS查詢耗時
13. connectTime:TCP連接耗時
14. requestTime:內容加載完成的時間
15. requestDocumentTime:請求文檔時間,開始請求文檔到開始接收文檔
16. responseDocumentTime:接收文檔時間,開始接收文檔到文檔接收完成
17. TTFB(Time To First Byte):讀取頁面第一個字節的時間
二、資源載入信息
performance對象中有個getEntries方法,通過此方法可以將頁面中的資源載入情況記錄下來。
可以繪制出像下圖那樣的瀑布圖。
然而此方法兼容性非常差,我在紅米手機中測試,UC不行,自帶的瀏覽器倒是可以將信息打印出來。
在插件中也稍微封裝了一個方法“getEntries”,在兼容的瀏覽器中可以采集到相關數據。
1. name:資源的完整路徑,例如“http://localhost:63342/web/strick/Primus/ajax/data2.json”
2. fileName:文件名。例如“data2.json”
3. duration:資源載入總共消耗的時間
4. requestStartDelay:開始請求延時時間
5. lookupDomainTime:DNS 查詢時間
6. connectTime:TCP 建立連接完成握手的時間
7. TTFB:讀取資源第一個字節的時間
8. requestTime:內容加載完成的時間
9. requestDuration:請求區間
10. redirectTime:重定向的時間
在一些商業性能采集的應用中,我看到有瀑布圖的展示,不知道他們是怎么搞的。
三、網絡狀態
網絡狀況 API“navigator.connection”也是個很有用的參數,然而兼容性也是非常差。
網絡狀態就是獲取當前是“WIFI 2G 3G 4G”等。
如果能獲取到這個參數,就能准確知道頁面在不同網絡狀態中展現的情況。
四、網速
沒有專門的API提供當前用戶的網速,但可以通過下載某個大文件來計算。
目前只知道這種方法,感覺實用性不是很大。
在index.html中寫了個例子,將圖片放到某個服務器下面會更准確一些。
五、AJAX監控
現在的頁面上面充斥着大量的ajax請求,可以將請求的信息保存起來有助於分析性能。
在項目中使用Zepto庫、jQuery等封裝好的庫,最后還是會調用原生的“XMLHttpRequest”
可以重新一下“XMLHttpRequest”對象,在這個對象的幾個步驟中埋入要統計的點。
window.XMLHttpRequest = function(flags) { var req; // 調用原生的XMLHttpRequest req = new _XMLHttpRequest(flags); // 埋入我們的“間諜” monitorXHR(req); return req; };
在open和send中也埋入統計的方法,通過這種方式就能獲取到信息了,下圖就是統計的信息。
六、UA信息和分辨率
1)UA信息
每個請求頭中都會帶有“User-Agent”屬性,通過這個屬性可以分析出OS、Device、Browser、Platform等信息。
我自己沒有封裝這個頭,網上有很多插件可以做分析的工作,不過JS的話有點大。
國外有“UAParser.js”,關注量1400多了,不過簡單測試下來,對於國內手機的分析不是很給力,如果要用的話還得自己修改下源碼。
國內有“useragent”,有js和php多個版本,小測了一下,國內手機辨別率還挺高的。
2)分辨率
這個比較簡單就是獲取屏幕的物理寬度和高度,一句話就能獲取。
primus.dpi = function() { return {width:window.screen.width, height:window.screen.height}; };
尺寸坐標可以參考我以前寫的一篇博文《JavaScript中尺寸、坐標》
七、異常監控
異常監控就是監聽“window.onerror”事件,在這個事件內能夠獲取到錯誤提示信息,行數,列數,錯誤地址。
/** * 異常監控 * https://github.com/BetterJS/badjs-report * @param {String} msg 錯誤信息 * @param {String} url 出錯文件的URL * @param {Long} line 出錯代碼的行號 * @param {Long} col 出錯代碼的列號 * @param {Object} error 錯誤信息Object https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error */ window.onerror = function(msg, url, line, col, error) { var newMsg = msg; if (error && error.stack) { var stack = error.stack.replace(/\n/gi, "").split(/\bat\b/).slice(0, 9).join("@").replace(/\?[^:]+/gi, ""); var msg = error.toString(); if (stack.indexOf(msg) < 0) { stack = msg + "@" + stack; } newMsg = stack; } var obj = {msg:newMsg, target:url, rowNum:line, colNum:col}; alert(obj.msg); };
八、數據發送與引用
1)數據發送
為了更好的跨域,數據發送通過設置Image對象的src來實現。
簡單的將各個收集過來的數據作為URL中的參數傳過去,代碼中可能有BUG。
發送以后就是保存數據了,可以將數據保存在Hadoop中。
2)Primus的引用
由於要計算白屏時間,dom時間等,所以位置不能隨便放,得要放在head的最后面。
如果要做點初始化配置也是完全OK的。
<head> <script type='text/javascript'> window.primus || (primus={}); primus.param = { "token":"dsadasd2323dsad23dsada", "backgroundImages":[] }; </script> <script src="js/primus.js"></script> </head>
源碼下載:
https://github.com/pwstrick/Primus
參考資料:
Browser Monitoring for GitHub.com