JavaScript錯(cuò)誤對(duì)性能的影響
?雖然Web性能的實(shí)踐已經(jīng)存在了一段時(shí)間,并且多年來(lái)研究和調(diào)試JavaScript (JS)錯(cuò)誤的能力有所提高,但我們從未真正關(guān)注過錯(cuò)誤對(duì)性能的影響。
JavaScript錯(cuò)誤是Akamai的真實(shí)用戶監(jiān)控 (RUM) 工具 (mPulse ) 收集的更復(fù)雜的指標(biāo)之一,作為一名數(shù)據(jù)科學(xué)家,我已經(jīng)研究這些數(shù)據(jù)幾年了。在這篇文章中,我將談?wù)勎业囊恍┌l(fā)現(xiàn)。
挑戰(zhàn)
那么,我們?cè)诜治鯦S錯(cuò)誤時(shí)從哪里開始呢?任何JS錯(cuò)誤跟蹤服務(wù)的用戶都會(huì)立即觀察到唯一錯(cuò)誤的數(shù)量增長(zhǎng)得非???。這使得在數(shù)據(jù)中找到模式并最終診斷站點(diǎn)上的問題區(qū)域變得極其困難。幸運(yùn)的是,許多獨(dú)特的錯(cuò)誤并不是真的那么獨(dú)特。事實(shí)上,許多錯(cuò)誤彼此非常相似,只是在語(yǔ)法上略有不同。這些變化可能由于多種原因而發(fā)生,例如(但不限于):
(1)瀏覽器如何呈現(xiàn)錯(cuò)誤的差異:
參數(shù)列表后缺少 )
SyntaxError: missing ) 在參數(shù)列表之后
(2)相同的錯(cuò)誤對(duì)象引用出現(xiàn)在不同的數(shù)組索引處:
錯(cuò)誤:無(wú)法解析具有未知索引“5”的 iframe
錯(cuò)誤:無(wú)法解析具有未知索引“7”的 iframe
錯(cuò)誤:無(wú)法解析具有未知索引“21”的 iframe
(3)不同變量名稱的相同邏輯錯(cuò)誤:
ReferenceError: '$' 未定義
ReferenceError: 't' 未定義
ReferenceError: 'f' 未定義
根據(jù)客戶的不同,此類類似錯(cuò)誤消息的出現(xiàn)可能會(huì)在JS錯(cuò)誤數(shù)據(jù)中出現(xiàn)數(shù)十到數(shù)百次。我們通過重復(fù)數(shù)據(jù)刪除并對(duì)一組更易于管理的錯(cuò)誤進(jìn)行分析,從而利用這些共性來(lái)發(fā)揮我們的優(yōu)勢(shì)。
例如,上面的第二組錯(cuò)誤將成為一組錯(cuò)誤,其形式為“錯(cuò)誤:無(wú)法解析具有未知索引 <*> 的iframe”,其中 <*> 是索引值的占位符。
為什么對(duì)錯(cuò)誤計(jì)數(shù)發(fā)出警報(bào)還不夠
了解JS錯(cuò)誤何時(shí)發(fā)生以及跨越哪些頁(yè)面是了解錯(cuò)誤對(duì)網(wǎng)站的影響的重要第一步。然而,簡(jiǎn)單地監(jiān)控發(fā)生的錯(cuò)誤數(shù)量并不能為監(jiān)控整個(gè)網(wǎng)絡(luò)流量提供任何額外的好處。
這里的原因是許多頁(yè)面包含JS錯(cuò)誤,因此,錯(cuò)誤的數(shù)量幾乎與Web流量的規(guī)模完全相關(guān)。我的mPulse 產(chǎn)品團(tuán)隊(duì)引入了一個(gè)名為“每頁(yè)錯(cuò)誤數(shù)”的指標(biāo)來(lái)解決這個(gè)問題。
“每頁(yè)錯(cuò)誤數(shù)”定義為JS錯(cuò)誤數(shù)除以感興趣時(shí)間段的頁(yè)面瀏覽量。這使我們能夠意識(shí)到并及時(shí)了解錯(cuò)誤數(shù)量相對(duì)于信標(biāo)數(shù)量激增的時(shí)間。雖然這個(gè)指標(biāo)非常有用,但不幸的是,由于JS錯(cuò)誤的性質(zhì),它并不完美。在某些情況下,錯(cuò)誤很普遍,但卻是良性的。也就是說,錯(cuò)誤發(fā)生率高并不一定等同于糟糕的用戶體驗(yàn)或?qū)W(wǎng)絡(luò)性能的影響。在不了解其他信息的情況下,我們無(wú)法確定這種廣泛存在的錯(cuò)誤是否真的具有影響力或只是以高發(fā)生率發(fā)生。出于這個(gè)原因,我們必須深入研究Web性能指標(biāo)以獲得更清晰的畫面。
表現(xiàn)
雖然較慢的頁(yè)面通常會(huì)導(dǎo)致糟糕的用戶體驗(yàn),但重要的是要密切關(guān)注似乎已經(jīng)顯著改善的指標(biāo)——那些幾乎好得令人難以置信的指標(biāo)。想象一個(gè)頁(yè)面被破壞到頁(yè)面加載過程完全中斷并且頁(yè)面加載速度非??斓那闆r。負(fù)責(zé)監(jiān)控網(wǎng)站健康狀況的人員可能會(huì)對(duì)與這些頁(yè)面相關(guān)的錯(cuò)誤感興趣。
在我們的一項(xiàng)分析中,我們查看顯示錯(cuò)誤的頁(yè)面與不存在該特定錯(cuò)誤的類似頁(yè)面。然后,我們使用此分叉來(lái)檢查各種頁(yè)面加載過程的時(shí)間,以查看錯(cuò)誤出現(xiàn)和不出現(xiàn)的時(shí)間是否存在差異。在這里,我們并排繪制了顯示兩種情況的頁(yè)面加載時(shí)間 (ms) 分布的箱線圖。
在圖1中,我們看到了一個(gè)示例,該示例展示了當(dāng)網(wǎng)站上不存在錯(cuò)誤(左)時(shí)的頁(yè)面加載時(shí)間分布與存在此錯(cuò)誤時(shí)的類似頁(yè)面(右)相比,頁(yè)面加載時(shí)間分布顯著加快。
△圖1
在圖2中,我們看到了一個(gè)相反情況的示例——當(dāng)出現(xiàn)錯(cuò)誤時(shí),頁(yè)面速度顯著變慢(在中位數(shù)處慢兩倍多)。事實(shí)證明,這種情況更為常見。
△圖 2
最后,在圖3中,我們遇到了一個(gè)潛在良性錯(cuò)誤的情況,無(wú)論是否存在錯(cuò)誤,頁(yè)面加載過程都沒有太大差異。
△圖 3
JavaScript 錯(cuò)誤的間接副作用
在分析RUM數(shù)據(jù)中的JS錯(cuò)誤時(shí),我們開始考慮最終用戶在面對(duì)致命或破壞其流程的錯(cuò)誤時(shí)可能會(huì)表現(xiàn)出什么樣的行為。我們?cè)跀?shù)據(jù)中看到,某些錯(cuò)誤的存在會(huì)導(dǎo)致用戶沮喪的行為,這對(duì)服務(wù)于網(wǎng)站的業(yè)務(wù)有底線影響。兩個(gè)最突出的情況是重新加載和放棄(頁(yè)面退出)。
重新加載
在JS錯(cuò)誤的上下文中,我們認(rèn)為會(huì)話中下一頁(yè)的重新加載(特別是重新加載的高發(fā)生率)表明錯(cuò)誤本身與導(dǎo)致用戶沮喪的頁(yè)面相關(guān)聯(lián)。重新加載可能由多種原因引起,包括:
(1)由于頁(yè)面加載時(shí)間過長(zhǎng)而導(dǎo)致的不耐煩
(2)頁(yè)面上的某些內(nèi)容未正確呈現(xiàn)
(3)該頁(yè)面顯示非200級(jí)響應(yīng)代碼
要點(diǎn)是,高重新加載率會(huì)提醒我們發(fā)生錯(cuò)誤的頁(yè)面上的特定問題。
出口
知道用戶退出頁(yè)面的原因并不總是顯而易見的,尤其是與JS錯(cuò)誤有關(guān)的情況。通常,用戶退出或結(jié)束會(huì)話并不值得關(guān)注。例如,考慮一個(gè)用戶剛剛完成了他們?cè)诰W(wǎng)站上的預(yù)期操作(進(jìn)行了購(gòu)買、找到并閱讀了特定文章等)。在這種情況下,退出站點(diǎn)是用戶會(huì)話的自然結(jié)束。但是,由于網(wǎng)頁(yè)速度慢或損壞,用戶可能會(huì)比預(yù)期更快地退出站點(diǎn)。在這里,我們對(duì)這些頁(yè)面上出現(xiàn)的JS錯(cuò)誤特別感興趣。
在此分析中,我們檢查了在訪問出現(xiàn)特定錯(cuò)誤的頁(yè)面后會(huì)話(訪問的頁(yè)面數(shù))持續(xù)了多長(zhǎng)時(shí)間。例如,考慮以下5個(gè)框給出的包含5個(gè)頁(yè)面的會(huì)話。
△圖 4
假設(shè)我們?cè)诘?頁(yè)上看到一個(gè)錯(cuò)誤,比如錯(cuò)誤XYZ。假設(shè)會(huì)話長(zhǎng)度為5頁(yè),則在看到錯(cuò)誤XYZ后會(huì)話中剩余的頁(yè)數(shù)為2頁(yè)。
△圖 5
但是,如果我們?cè)跁?huì)話的第5頁(yè)上看到錯(cuò)誤XYZ表面,則會(huì)話中剩余頁(yè)面的數(shù)量將為0。換句話說,會(huì)話在訪問具有此錯(cuò)誤XYZ的頁(yè)面后結(jié)束。
△圖 6
在此分析中,我們?cè)诳吹矫糠N類型的錯(cuò)誤后匯總了會(huì)話中剩余頁(yè)面的值。然后很明顯,在用戶會(huì)話的最后一頁(yè)上完全(或幾乎完全)發(fā)現(xiàn)了客戶網(wǎng)站上的某些錯(cuò)誤。這些將是我們將進(jìn)一步挖掘的錯(cuò)誤,以找出可能導(dǎo)致用戶會(huì)話結(jié)束的原因。
圖7使用一系列并排的箱線圖顯示了這種分析。每個(gè)錯(cuò)誤都有自己的箱線圖,沿x軸用名稱表示。y軸顯示看到錯(cuò)誤后會(huì)話中的剩余頁(yè)面。剩余頁(yè)面的廣泛分布表明在錯(cuò)誤浮出水面后有許多可能的用戶旅程。我們可能會(huì)得出結(jié)論,雖然該錯(cuò)誤可能對(duì)某些用戶造成了破壞,但它并沒有阻止大多數(shù)用戶繼續(xù)他們的會(huì)話。這些案例位于圖7的右側(cè)。
△圖 6
更有趣的是,圖表左側(cè)更緊密的分布顯示了似乎影響用戶繼續(xù)會(huì)話能力的錯(cuò)誤。具體來(lái)說,最左邊的四個(gè)錯(cuò)誤就是我們所說的會(huì)話殺手。每次用戶訪問存在這些錯(cuò)誤之一的頁(yè)面時(shí),在每種情況下,會(huì)話都會(huì)停止繼續(xù)。
通常,此類破壞性錯(cuò)誤出現(xiàn)在一組特定的頁(yè)面尺寸值上。例如,特定版本的瀏覽器、特定頁(yè)面組、特定操作系統(tǒng)、特定地理位置,或者有時(shí)是所有這些的組合。準(zhǔn)確了解錯(cuò)誤導(dǎo)致性能下降的位置為開發(fā)人員維護(hù)站點(diǎn)的健康提供了明確的行動(dòng)計(jì)劃。
結(jié)論
隨著網(wǎng)絡(luò)性能工具變得越來(lái)越復(fù)雜,我們收集的數(shù)據(jù)以及我們打算用這些數(shù)據(jù)回答的問題也越來(lái)越復(fù)雜。雖然我們有關(guān)于JS錯(cuò)誤的數(shù)據(jù),但分析它并不總是一個(gè)簡(jiǎn)單的問題。我們的目標(biāo)是消除這些數(shù)據(jù)中的噪音,并查明對(duì)性能有實(shí)際影響并因此導(dǎo)致最終用戶體驗(yàn)下降的JS錯(cuò)誤。
對(duì)我和我的團(tuán)隊(duì)來(lái)說,圍繞JS錯(cuò)誤的分析仍然是一個(gè)活躍的研究領(lǐng)域。我歡迎對(duì)上述信息提出任何問題、意見、疑慮和一般反饋。
[1] JavaScript錯(cuò)誤是通過啟用錯(cuò)誤插件的開源boomerang.js 包收集的。
[2] 我們運(yùn)行基于JS錯(cuò)誤之間的字符串編輯距離的聚類算法。這種分析使我們能夠根據(jù)錯(cuò)誤返回的字符串將我們認(rèn)為具有相同來(lái)源的錯(cuò)誤分組在一起。在上面的示例中,我們將提供一組錯(cuò)誤的聚合Web 性能指標(biāo)值,而不是單獨(dú)的單個(gè)錯(cuò)誤。這個(gè)集群和聚合步驟使得從數(shù)據(jù)中收集見解和確定網(wǎng)站上JS錯(cuò)誤的性能影響變得更加容易。
[3] 為了維護(hù)客戶數(shù)據(jù)的機(jī)密性,我有意省略了下圖中所討論的具體錯(cuò)誤。
[4] 通過performance.navigation.type返回值1給出重新加載。在計(jì)算重新加載率時(shí),我們感興趣的是在看到當(dāng)前頁(yè)面上的錯(cuò)誤后,在會(huì)話中的下一頁(yè)上發(fā)生這種情況的次數(shù)。
[5] 請(qǐng)注意,具體的錯(cuò)誤名稱替換為隨機(jī)生成的字符串。
*原文鏈接:https://calendar.perfplanet.com/2021/performance-implications-of-javascript-errors/?