自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

性能指標的信仰危機

原創(chuàng) 精選
開發(fā) 前端
我觀察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監(jiān)控時是一個被“喂”的過程,即會慣性的不假思索的收集已有指標和利用已有工具。

正在閱讀這篇文章的你,或多或者接觸過前端性能優(yōu)化,這樣的接觸可能是來自你的閱讀體驗也可能是來自工作經(jīng)驗。那我們不妨從一個非常簡單的思想實驗開始,請你借助你對這個領域的理解,來回答下面的幾個問題:

  • 假設現(xiàn)在由你來主導一項優(yōu)化公司站點性能的工作,你會選取哪些指標用于衡量性能?
  • 假設你選取了某個或者某幾個指標納入到監(jiān)控的范疇內(nèi),當頁面性能出現(xiàn)問題時,你是否能通過它們及時發(fā)現(xiàn)問題?
  • 假設你發(fā)現(xiàn)某個頁面的性能出現(xiàn)了問題需要立刻修復,這幾個指標能否幫助你快速定位問題?

不要有壓力,你可以慢慢思考并回答這幾個問題,你關于第一個問題的答案可能會隨著二三問題的出現(xiàn)而不斷的調(diào)整。

這篇文章的目的就是對上面三個問題的探索和嘗試性的解答,希望我的答案能帶給你一些啟發(fā)。

一次復盤

目前我所在的項目上長時間都依賴都 GA (Google Analytic) 作為衡量頁面性能的唯一工具,在 GA 的生態(tài)圈中,我們最為重視的是 Avg Page Load Time (以下簡稱為 APLT),通過它來斷定我們站點當前的性能狀態(tài)如何。

但是在定期收集該指標數(shù)據(jù)的過程中,我們發(fā)現(xiàn)用戶的感受和數(shù)據(jù)的展示可能并不一致,具體來說數(shù)據(jù)看上去波瀾不驚,但用戶體驗卻直線下降。

所以我們不得不要回答一個至關重要的問題,APLT 衡量的究竟是什么?

什么這個問題之所以至關重要,是因為它的答案決定我們接下來要解決的問題和需要采取的行動:

  • 為什么 APLT 衡量的結果與客戶感受到的不一致?差距在哪里?差距有多少?
  • 每當數(shù)值出現(xiàn)波動時,我們會下意識的懷疑是前端腳本拖慢了性能,但腳本對這個指標影響有多少?我們的懷疑是否有道理?以及是否存在其他的可能性?
  • 如果 APLT 變慢了?有哪些可能導致 APLT 變慢?這決定著我們排查問題的方向。
  • 如果 APLT 不夠準確,我們需要自定義指標重新衡量性能結果,我們能從中吸取什么經(jīng)驗?我們的指標可否與 APLT 產(chǎn)生聯(lián)動產(chǎn)生一加一大于二的效應?

然而官方文檔對于這個指標的解釋是很曖昧的:

Avg Page Load Time : The average amount of time (in seconds) it takes that page to load, from initiation of the pageview (e.g., click on a page link) to load completion in the browser.

Avg. Page Load Time consists of two components: 1) network and server time, and 2) browser time. The Technical section of the Explorer tab provides details about the network and remaining time is the browser overhead for parsing and executing the JavaScript and rendering the page.

對于它的解釋,我們產(chǎn)生了幾點疑問:

  • “l(fā)oad completion”是如何被定義的?之所以要回答這個問題是因為它是作為指標衡量的終點而存在。
  • server time 僅僅包含一切靜態(tài)資源嗎?異步請求會被計算在內(nèi)嗎?

GA 的實現(xiàn)

GA 底層是通過 Navigation Timing API 在采集性能數(shù)據(jù):

GA 不會統(tǒng)計每一個階段的數(shù)據(jù),它將某些合并后重新命名成新的指標,而其中的某些指標比如 Document Interactive Loaded 其實是某些階段的統(tǒng)計之和:

GA 統(tǒng)計的僅僅是與 DOM 文檔有關的數(shù)據(jù)。APLT 定義里所說的 load completion 時刻指的就是 loadEventEnd 事件的發(fā)生時機,即 onLoad 事件觸發(fā)完畢(load 事件觸發(fā)時意味著所有的外部資源,包括 iframe、圖片、腳本、樣式都已經(jīng)加載完畢)。所以 APLT 值是 GA 里所有指標里橫跨時間范圍最廣的。

腳本對 Avg Page Load Time 的影響是什么

如上圖所示,當瀏覽器自上而下解析 DOM 樹時,它會遇見很多外聯(lián)資源,比如圖片、樣式和腳本。于是它需要從緩存或者網(wǎng)絡中請求這些資源。

頁面的解析是同步的,所以腳本的加載會導致頁面解析的暫停。瀏覽器需要在腳本加載、編譯、執(zhí)行完畢之后才會繼續(xù)之后的解析工作,這么做是有道理的,因為 JavaScript 可能會使用諸如 document.write() 方法來改變 DOM 的結構。你可能聽說過在 script 標簽上添加 async 或者 defer 屬性來異步的加載和執(zhí)行腳本。但是它在我們的產(chǎn)品中是不適用的,因為 async 無法保證腳本執(zhí)行的順序。但這則方案不一定適用于所有頁面,因為 async 無法保證腳本的執(zhí)行順序,如果你的應用對腳本的執(zhí)行順序有嚴格要求,那么它對你愛莫能助。

目前瀏覽器都配備preloader機制來提前掃面頁面中的外聯(lián)元素提前加載,但這個機制并無統(tǒng)一的標準也無法衡量效果,所以暫時不考慮它對我們的影響。

腳本下載之后需要經(jīng)過解析(parse / compile)和執(zhí)行(run / execute)。解析階段首先將 javascript 代碼編譯為機器語言,執(zhí)行階段才會真正的運行我們編寫的代碼。腳本的解析和執(zhí)行也會阻塞頁面的解析

所以綜上,我們可以得出腳本確實能夠影響 APLT 。

但拋棄計量談危害都是刷流氓,它的影響范圍究竟有多大?也就是說如果 APLT 是 2 秒的話,其中多少時間耗費在了腳本上?

這里沒有一個具體的數(shù)字,但它不容小覷,以及足夠影響到性能。Addy Osmani 在 2017 年的一篇文章中指出 Chrome 的腳本引擎花費在編譯時間上:

雖然此后 Chrome 對編譯過程進行了優(yōu)化,但執(zhí)行腳本過長的困惱依然存在。同時這只是 Chrome 下的情況,我們無法確認其他瀏覽器在編譯腳本時也可以保證同樣的效率

如果說 APLT 是由不同的階段組成,那么我們有沒有可能計算出每一個階段的具體時間?

回顧上面關于 GA 指標的定義,至少我們現(xiàn)在能分離出 server time 和 browser time. 但是在 browser time 之下呢?比如說腳本的下載時間和執(zhí)行時間,這些我們就無從得知了。這些是需要額外計算和采集的。

綜上,我們完全依賴 APLT 來對站點的性能問題進行診斷是不靠譜,我們單純的認為腳本負擔拖慢了性能也是不完整的。

一場關于指標的信仰危機

我想你大概明白了為什么我在上一節(jié)中花了這么大段的篇幅來解釋僅僅一個指標的含義。因為一個指標能透露的信息可能會比你想象的要復雜,引導和誤導并存。

首先要聲明我并不反對使用常見指標,這篇文章也不是對它們的批評,它們在幫助我們排查性能問題方面給了非常大的幫助。在這里我想探討的是,如果常規(guī)指標是性能監(jiān)控的底線的話,它的上限在哪?

從上面的描述中我們不難看出 APLT 的涉獵的維度過于寬泛,它更偏向于一個技術向的綜合性指標,它展示給我們是趨勢而非細節(jié)。這樣帶來的問題有兩個:

  • 指標指數(shù)與實際的產(chǎn)品體驗不符
  • 它無助于我們排查具體的性能問題

接下來我們深入的聊聊這兩個問題。

以用戶為中心

你或許有留意到,目前前端性能監(jiān)測的趨勢逐漸在向以用戶為中心的指標 (User-Centric Performance Metrics) 靠攏。為什么會出現(xiàn)這樣的情況?因為隨著單頁面應用的普及以及前端功能變“重”,經(jīng)典的以資源為中心的性能指標(例如 Onload, DOMContentLoaded)越來越不能準確地反饋真實用戶的體驗與產(chǎn)品性能。在傳統(tǒng)后端渲染的多頁面應用模式下,資源加載完畢即意味著頁面對用戶可用;而在單頁面模式下,資源加載完畢距離產(chǎn)品可用存在一定的差距,因為此時應用才能真正地請求用戶個性化的數(shù)據(jù),渲染定制化的頁面。

總的來說,越來越多重要且耗時的工作都發(fā)生在資源加載之后,我們需要把這部分工作的性能也監(jiān)控起來。

好消息是瀏覽器原生的在提供給予我們這方面的支持,例如 Chrome 就在 Performace API 中提供了 Paint Timing API 諸如 first paint (FP) 、 first contentful paint (FCP)、time to interact(tti) 等指標數(shù)據(jù)。顧名思義的這些指標嘗試站在用戶體驗的視角展現(xiàn)應用在瀏覽器中被呈現(xiàn)時的性能;壞消息是,這些指標依然在測量真實的用戶體驗方面依然存在誤差。

就以上面提到的 FP、FCP、TTI 這三個指標為例,我用一個簡單的例子說明這三個指標是如何不夠準確的:在單頁面的初始化過程中,我們通常會提供類似于「加載中」視圖,通常是一個 placeholder 或者 skeleton 樣式,在數(shù)據(jù)請求完畢之后才會將實際的視圖渲染出來:

如果加載時間過長,瀏覽器會以為「加載中」視圖就是對用戶可用的最終產(chǎn)品形態(tài),并以它為基準計算那上述的三個指標。

下面這段代碼模擬的就是包含上面所說情況的日常情況:在組件加載時模擬發(fā)出兩個請求,其中一個需要5秒較長的等待時間,只有當兩個請求都返回時才能開始渲染數(shù)據(jù),否則一直提示用戶加載中。

function App() {
const [data, setState] = useState([]);
useEffect(() => {
const longRequest = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([]);
}, 1000 * 5)
});
const shortRequest = Promise.resolve([]);

Promise.all([longRequest, shortRequest]).then(([longRequestResponse, shortRequestResponse]) => {
setState([
['', 'Tesla', 'Mercedes', 'Toyota', 'Volvo'],
['2019', 10, 11, 12, 13],
['2020', 20, 11, 14, 13],
['2021', 30, 15, 12, 13]
])
})
}, []);
return (
<div className="App">
{data && data.length
? <HotTable data={data} />
: <Skeleton count={15}/>}
</div>
)
}

如果你嘗試在瀏覽器中運行上述 App, 通過 Devtools 觀測到的各個指標如下:

你能通過開發(fā)者工具夠觀測到各種指標比如 DCL (DOMContentLoaded Event), FP, FCP, FMP (first meaningful paint), L(Onload Event) 都發(fā)生在頁面加載后一秒左右以內(nèi)。然而從代碼里我們非??隙ㄖ辽傥迕牒笥脩舨拍芸吹秸鎸崈?nèi)容。所以上述指標并不能真的反饋用戶感受到的性能問題

我已經(jīng)把這個應用部署到了 https://cheat-web-page-test.com/ 站點上,可以在線訪問。并且可以使用 https://www.webpagetest.org/ 對它做更詳細的性能檢測,也會得出和 devtools 相同的結果。webpagetest 是一個開源免費對網(wǎng)站性能進行檢測的工具。早在 2012 年還沒有諸如 FP 一類的指標時,它獨創(chuàng)的 Speed Index 指標就能夠衡量用戶體驗。

總的來說如上圖所示,目前瀏覽器提供的 API 能夠測量的只是 D 階段的性能,對 E 和 F 階段愛莫能助。

這只是其中一個說明原生指標不夠準確的例子,可以歸納為后端接口延遲過長。然而還有一種情況是前端渲染時間過長。例如我們在使用 Handsontable 組件渲染上千行數(shù)據(jù)表格的時候,甚至導致了瀏覽器的假死,這種場景對 Paint Timing API 也是免疫的。

那 tti 這個指標怎么樣?它不是聽上去能夠檢測頁面是否可以交互嗎?它是不是能夠檢測頁面的假死?

很遺憾依然不行。

如果你有心去查看 tti 這個指標的定義的話, 你會發(fā)現(xiàn) tti 本質(zhì)上是一種算法:

  • 首先找到一個接近 tti 的零界點,比如 FirstContentfulPaint 或者 DomContentLoadedEnd 時機
  • 從臨界點向后查找不包含長任務 (long task) 的并且網(wǎng)絡請求相對平靜的 5 秒鐘窗口期
  • 找到之后,再向前追溯到最后一個長任務的執(zhí)行結束點,那就是我們的要找的 tti

并且目前的原生 API 并不支持 tti 指標,需要通過 polyfill 實現(xiàn),按照官方的說明,目前并不能適配所有的 web app。

雙向指標

這是知乎創(chuàng)作者中心頁面的一個截圖:

在這個頁面中,知乎每天都會為你更新過去七天內(nèi)文章閱讀數(shù)、贊同數(shù)、評論數(shù)等數(shù)據(jù)的匯總。上圖中的折線就是閱讀數(shù)。

我知道它的用意是想給予創(chuàng)作者數(shù)據(jù)上的反饋幫助他們更好的輸出內(nèi)容,但至少對我來說一點用也沒有。因為我更想知道的是究竟增長來自于哪里,這樣我才能有針對性的輸出帶來點擊量的內(nèi)容。但它帶給我的總是匯總數(shù)據(jù)。

這個需求對于性能監(jiān)控也是同樣的成立的,監(jiān)控的目的主要是為了及時發(fā)現(xiàn)問題,解決問題。所以在審視數(shù)據(jù)的過程中,我們更關心的是異常波動值發(fā)生在何時何地,我們也希望數(shù)據(jù)能給予我這方面的幫助。

當然我們不可能無中生有的將一組匯總數(shù)據(jù)還原成細節(jié)數(shù)據(jù),但在這個問題上我們可以往兩個方向努力:

  • 保留向細節(jié)追溯的能力:雖然我們最終看到的是匯總數(shù)據(jù),但依然可以查詢到用于聚合計算使用的單次數(shù)據(jù)
  • 更有針對性的收集數(shù)據(jù):如果你已經(jīng)意識到高層次的指標數(shù)據(jù)對你來價值有限,那么不妨有針對性的收集你需要的數(shù)據(jù),這在下一節(jié)會談到。

在 Web Performance Calendar 2020 Edition 中 A wish list for web performance tools 一文中,作者提出了關于他理想性能工具應該滿足的四則功能,分別是:

  • Predict Web Performance as early as possible
  • Don’t let me do the hard work
  • Make data actionable
  • Protect the environment

其中的第二三則對于我們選擇指標來說也是成立的,與我在上面的強調(diào)的不謀而合。

最后再一次強調(diào)這里不是對傳統(tǒng)指標的否定。數(shù)據(jù)帶來的效果一定是聊勝于無,指標越多越是能精確的描繪出性能畫像。這里探討的是如何在這些基礎上繼續(xù)事半功倍提升我們洞察問題的效率。

在選擇衡量指標上的一些建議

上下文驅(qū)動 (Context Driven)

之所以我無法在這里給你一個大而全的解決方案,是因為我認為這種東西并不存在,一切都要依賴你的上下文而定。

你也許更熟悉的是上下文驅(qū)動測試(Context Driven Testing),但在我看來,上下文驅(qū)動在你選擇性能指標或者工具時也是同樣成立的。我們不妨看一看上下文測試七條原則中的頭兩條:

  • The value of any practice depends on its context. (任何實踐的價值都依附于它所處的上下文)
  • There are good practices in context, but there are no best practices. (在同一塊上下文呢中會有各式各樣好的實踐,但永遠不會有最佳實踐)

想象一下如果你把兩句話中的 practice 理解為指標(metric),甚至直接替換為指標,是不是也沒有任何違和感呢?

“上下文驅(qū)動”初看上去不過是正反話,但實際上它是我們提升監(jiān)測效率的有效出路。指標本身不會有對錯之分,但不同人群對于指標的視角是割裂的:業(yè)務分析師希望得到的是能直接彰顯業(yè)務價值的數(shù)據(jù),例如點擊率,彈出率,用戶轉(zhuǎn)化;DevOps 同學他們可能關心的是網(wǎng)站的“心跳”,資源的消耗,后端接口的快慢;所以不同指標在不同人群中是一種此消彼長的狀態(tài)。這種割裂還可以從技術角度上劃分,有的指標更側重于資源,有的指標更側重于用戶感受。

指標只是發(fā)現(xiàn)問題的一種手段,現(xiàn)在我們有無數(shù)種手段任君挑選:APM (Application Performance Management)、日志分析、RUM (Real-User Monitoring)、TTFB (Time to First Byte)……最終它迫使你回到了問題的起點:我究竟想衡量什么?我想衡量的物體是否可以通過已有的指標表達出來?我只是想 monitor 嗎?如果我想 debug 或者是 analyze 的話是否還有其他的選擇?

“Good software testing is a challenging intellectual process.” (請把 testing 替換為 performance tuning)上下文驅(qū)動測試中的第六條原則如是說。

追蹤元素

如果說“資源加載完畢”這件事不靠譜,“瀏覽器開始繪制”也不靠譜的話,我想唯一靠譜的事情就是用戶的所見所得了。不需要用各種數(shù)據(jù)來展示你的頁面加載有多快,如果用戶每次都要等待十秒才能看到他想看到的信息,那么這些數(shù)字無非是自欺欺人而已。所以我們不妨可以追蹤用戶關注信息所對應元素的出現(xiàn)的時機。

這不是創(chuàng)新,從早些年的 Speed Index,“above the fold” 到如今的 web vitals 都是這種思想的延續(xù),指標的進化過程像一個不斷收縮過程中圓圈,在不斷的像用戶本身靠攏。只不過出于技術手段的限制,它們只能走到那么遠,而如今我們有了 MutationObserver 和 Perforamce API, 則可以精確的定位到元素,甚至元素上屬性的改變,自然也就不會被上面例子中的 placeholder 所欺騙。

抱歉我要在這里再次強調(diào)一下上下文:我們不能只關注“元素出現(xiàn)的時機”,更要從時間的范疇和從代碼延展上看關注形成它的原因,這依然需要我們結合問題所處的環(huán)境和它的運轉(zhuǎn)機制而定。舉兩個例子:

在上圖中,如果 Component D 是向客戶展示關鍵信息的關鍵元素,那么 request 到達 router 的時間,由 router 渲染出 Component C 的時間,都會對 D 元素產(chǎn)生影響;從另一個維度上看:

腳本以及請求加載的快慢和執(zhí)行的效率,同樣也會對元素的出現(xiàn)產(chǎn)生影響。如果你需要對問題進行診斷,對這些背后工作機制的了解必不可少。

但追蹤元素也存在另一個問題就是它難以大規(guī)模的應用。因為它是侵入式的,因為它需要你識別不同頁面上的不同關鍵元素,用近似于 hard code 的方式對它們一一追蹤。這類工作產(chǎn)生的維護成本接近于維護前端的 E2E 測試。誠然我們可以通過分配統(tǒng)一的 id 或者 class name 的方式來減少我們的維護成本,但是相比統(tǒng)一的 GA 代碼這樣的維護成本依然偏高。所以我建議使用最簡單的方法去監(jiān)控最直接的元素,不要 case by case 的去編寫你的監(jiān)控代碼,不要讓你的實現(xiàn)代碼被監(jiān)控代碼束縛住。

讓工具為你所用

你可以在市面上找到各類數(shù)不勝數(shù)號稱能夠協(xié)助你改善性能的工具。但首先你要小心,它們所宣揚的,并非是你真正需要的。

例如 site24x7 是一家專業(yè)提供用戶行為監(jiān)控解決方案的公司。在它們有關 APM 的幫助頁面上,開宗明義的指出了監(jiān)控捕獲 SAP(Single Page Application) 性能數(shù)據(jù)以目前的技術來說其實是一項頗具挑戰(zhàn)的工作:

In case of Single Page Applications, the time taken for page load completion cannot be obtained by page onload event since the data are dynamically obtained from the server using

Hence, for each SPA framework, the page load metrics are calculated by listening to particular events specific to the framework.

所以對于此種類型的頁面,它們捕獲指標也只有:

For every dynamic page load, the corresponding URL, it's respective AJAX calls, response time of each AJAX call, response codes and errors (if any) are captured.

但要知道在如今 SPA 大行其道的今天,如此的收集功能略顯的蒼白無力了。

同理如果你去看 Azure Application Insights 旗下 JavaScript SDK 默認收集的頁面信息:

(1) Uncaught exceptions in your app, including information on

  • Stack trace
  • Exception details and message accompanying the error
  • Line & column number of error
  • URL where error was raised

(2) Network Dependency Requests made by your app XHR and Fetch (fetch collection is disabled by default) requests, include information on

  • Url of dependency source
  • Command & Method used to request the dependency
  • Duration of the request
  • Result code and success status of the request
  • ID (if any) of user making the request
  • Correlation context (if any) where request is made

(3) User information (for example, Location, network, IP)

(4) Device information (for example, Browser, OS, version, language, model)

(5) Session information

我不認為這些指標和其他平臺提供的相比能帶來額外的價值,它能真的給我?guī)矶嗌僬嬲?“insights”。

另一方面,不要讓你的思維被工具限制?。翰灰耙驗?xx 工具只能做到這些,所以我只能收集這些指標”;而要“我想收集這些指標,所以我需要 xx 工具”。在這里我列舉一個我們在探索中的例子:用 OpenTracing 工具 Jaeger 去可視化前端性能圖表。

在這里我首先必須贊頌 Chrome 內(nèi)置 Performance 工具給我們調(diào)教性能帶來了極大的便利。但我們始終有一些額外的需求無法滿足。例如我希望能夠在結果呈現(xiàn)中做一些自定義的標記,又或者在 Performance Tab 下展示每一個請求從 connect 到 resposne 每個階段的狀態(tài)。

如下圖所示,于是我們跨界的使用了 Jaeger 開源工具來用于自定義指標的收集和展示,可以說是將不同緯度的指標以時間為線索將它們聯(lián)系起來,這樣一來頁面加載階段的狀態(tài)并能一覽無余的盡收眼底。便于定位問題的所在。

結束語

我觀察到對于大部分前端工程師而言,又或者曾經(jīng)的自己而言,在做性能監(jiān)控時是一個被“喂”的過程,即會慣性的不假思索的收集已有指標和利用已有工具。又因為性能優(yōu)化工作過程前置結果后置的關系,等到我們有需求發(fā)生時才會發(fā)現(xiàn)當下的結果并非是我們想要的。多一些思考才會讓我們的工作少一分浪費。

責任編輯:趙寧寧 來源: Thoughtworks洞見
相關推薦

2011-06-07 14:16:38

雙絞線

2013-08-04 23:33:08

Taobao JVMiflake圖像搜索引擎

2009-11-26 15:32:49

VS2005性能

2011-05-04 13:53:08

jQuery

2024-09-20 08:32:21

2023-11-20 09:48:13

Linux性能指標命令

2010-09-08 11:38:27

2013-06-17 10:19:30

交換機性能交換機參數(shù)交換機

2023-11-25 20:16:22

前端

2023-12-29 15:30:41

內(nèi)存存儲

2011-07-28 14:58:49

HP ProLiant服務器

2023-12-17 14:49:20

前端首屏時間

2023-05-19 07:49:50

2017-02-22 11:51:11

FortiGate企業(yè)級防火墻NGFW

2024-06-28 11:54:20

2020-10-19 08:53:08

Redis性能指標監(jiān)控

2018-01-04 09:23:21

WEB服務器性能

2009-12-11 15:17:35

2023-09-08 15:37:29

軟件開發(fā)性能

2009-11-17 10:14:27

核心路由器
點贊
收藏

51CTO技術棧公眾號