拋磚系列之前端性能分析工具
背景
上周接到一個(gè)性能問(wèn)題的線上反饋:“浙江客戶(hù)xxx報(bào)表展示超過(guò)20秒,小明看了相關(guān)接口響應(yīng)都在2秒內(nèi),希望我協(xié)助排查?!?/p>
聽(tīng)完這個(gè)簡(jiǎn)短的描述我猜測(cè)可能是客戶(hù)機(jī)房網(wǎng)絡(luò)問(wèn)題,為什么這么說(shuō)呢,從描述中我提取到這么幾個(gè)關(guān)鍵信息“個(gè)例,不是所有客戶(hù)”、“后臺(tái)響應(yīng)很快”,給我的感覺(jué)好像是機(jī)房出口帶寬滿(mǎn)了,當(dāng)然這只是猜測(cè),需要拿出具體的證據(jù)。
初步排查
“信任但需要確認(rèn)”,雖然我從研發(fā)口中得知后臺(tái)響應(yīng)很快,但是為了查問(wèn)題我還是把相關(guān)賬號(hào)要過(guò)來(lái)自己點(diǎn)了點(diǎn),也看了后臺(tái)的access log的確不慢,通過(guò)瀏覽器的Network -> Timing奇怪的發(fā)現(xiàn),有個(gè)提示會(huì)停留20s左右“CAUTION:request is not finished yet!(注意:請(qǐng)求尚未完成)”,之后才會(huì)展示各項(xiàng)指標(biāo)耗時(shí),但是耗時(shí)都不高。
這個(gè)表象似乎和我猜測(cè)機(jī)房出口帶寬滿(mǎn)的想法不謀而合,接下來(lái)就是剝繭抽絲,證實(shí)客戶(hù)機(jī)房網(wǎng)絡(luò)的確有問(wèn)題,提供證據(jù)讓實(shí)施反饋客戶(hù),客戶(hù)再去問(wèn)候信息管理部,信息管理部再去問(wèn)候運(yùn)營(yíng)商( 和toG的客戶(hù)打交道千萬(wàn)要謹(jǐn)慎,往往都會(huì)驚動(dòng)一個(gè)鏈條上的人 )。
由于我不是專(zhuān)業(yè)網(wǎng)工,對(duì)于網(wǎng)絡(luò)問(wèn)題也只能憑借自己的二把刀經(jīng)驗(yàn)來(lái)做一些診斷,如果有不對(duì)的地方,請(qǐng)大家一定要指正。
ping -n 50 xxx.com
我首先通過(guò)ping的方式來(lái)觀察是否有丟包情況,結(jié)論是網(wǎng)絡(luò)良好,沒(méi)有任何丟包情況。
接下來(lái)我又通過(guò)Wireshark抓包分析,本機(jī)發(fā)出請(qǐng)求到收到響應(yīng)的時(shí)間確實(shí)在2s之內(nèi),這樣看來(lái)報(bào)表展示慢和網(wǎng)絡(luò)似乎是沒(méi)關(guān)系,還需要繼續(xù)挖掘原因。
強(qiáng)烈推薦大家學(xué)習(xí)Wireshark,對(duì)于網(wǎng)絡(luò)學(xué)習(xí)、問(wèn)題排查真的是一把利劍。
懷疑一切
之前提出的疑點(diǎn)偏后端領(lǐng)域,現(xiàn)在排查一圈下來(lái)矛頭指向了前端,那就接著挖。
我看了報(bào)表頁(yè)面內(nèi)的js代碼,邏輯很簡(jiǎn)單,就是ajax查詢(xún)數(shù)據(jù)然后調(diào)用前端框架的setData方法,到底是哪段js代碼把整個(gè)頁(yè)面渲染給拖慢了呢。
我甚至懷疑是不是觸發(fā)了jquery框架的某個(gè)bug,為了證實(shí)這一點(diǎn)我將請(qǐng)求數(shù)據(jù)那段從jquery切到了最原始的XMLHttpRequest,依然很慢。
要是瀏覽器能記錄這個(gè)頁(yè)面渲染過(guò)程中發(fā)生了什么,每個(gè)階段的耗時(shí)分布,那排查問(wèn)題就方便多了,我想到了曾經(jīng)用過(guò)的skywalking、jaegertracing這類(lèi)鏈路追蹤工具,排查后端性能問(wèn)題很是方便。
最終借助搜索引擎找到了chrome的Performance,請(qǐng)搜索“chrome 前端性能優(yōu)化工具”詳細(xì)了解,真是好用,前后不到兩分鐘就找到了性能瓶頸點(diǎn)。
開(kāi)始采集
F12-Performance->點(diǎn)擊 開(kāi)始記錄->刷新頁(yè)面->等待頁(yè)面渲染完成->點(diǎn)擊
停止記錄
查看調(diào)用樹(shù)
點(diǎn)擊上圖紅框部分的Call Tree查看調(diào)用鏈路和每個(gè)節(jié)點(diǎn)的耗時(shí),重點(diǎn)關(guān)注耗時(shí)占比較大的調(diào)用棧,如下圖所示拖慢整個(gè)頁(yè)面渲染的元兇是jCommon.js中的兩個(gè)設(shè)置表格樣式的函數(shù)。
這兩個(gè)函數(shù)的觸發(fā)時(shí)機(jī)在jCommon.js的$(function(){}中,屬于通用邏輯,之所以其他客戶(hù)沒(méi)有受到影響,是因?yàn)槠渌蛻?hù)對(duì)于表格的個(gè)性化設(shè)置沒(méi)有開(kāi)啟,所以沒(méi)有執(zhí)行,我大體看了一下邏輯內(nèi)部有太多的遞歸+循環(huán)調(diào)用,遇到復(fù)雜(行列合并、嵌套)而且數(shù)據(jù)量大的表格就是一種噩夢(mèng),更細(xì)節(jié)的就不多說(shuō)了,不是本篇的重點(diǎn)。
解決辦法
“讓專(zhuān)業(yè)的人干專(zhuān)業(yè)的事”,因?yàn)榍岸宋也⒉簧瞄L(zhǎng),所以我將這個(gè)問(wèn)題的根治任務(wù)拋給了前端同學(xué),這塊代碼是必須要優(yōu)化的,太損耗性能。同時(shí)對(duì)于當(dāng)下的問(wèn)題我也給出了建議,在當(dāng)前報(bào)表頁(yè)面暫時(shí)剔除這段邏輯,初衷是用來(lái)提升用戶(hù)體驗(yàn),現(xiàn)在看來(lái)已經(jīng)嚴(yán)重影響到可用性。
總結(jié)
透過(guò)一個(gè)簡(jiǎn)單的性能問(wèn)題,聊聊筆者排查的思路和中途用到一些工具,最終借助瀏覽器的性能分析工具發(fā)現(xiàn)前端問(wèn)題代碼,對(duì)于陌生的領(lǐng)域一款良好的工具可以降低排查的門(mén)檻,事半功倍。