一個基於佈局的近似方法(A layout-based approach)css
[Public] Created: April 12, 2016
Last updated: June 6, 2016 Owner: Kunihiko Sakamoto <ksakamoto@chromium.org>
Status: draft Tracking bug
原文地址:https://docs.google.com/docum...
翻譯:psychola(第一次翻譯此類文章,有翻譯錯誤請指出哦,如若轉載請註明出處哦,謝謝(^U^)ノ~)個人githubhtml
「首次有效渲染」(First Meaningful Paint)是當頁面的主要內容出如今屏幕上花的時間。這將是咱們對於用戶感覺到的加載體驗的主要度量標準(Metric)。git
「主要內容」(primary content)的定義根據不一樣頁面而有所不一樣。對於博客裏的文章,它是上面的標題+¬-摺疊文本(above-the-fold text),而且文本必須是可見的,¬而¬不是在等待字體加載。對於搜索引擎,它是搜索結果。若是一個圖片對於頁面來講很重要(例如e-commerce產品頁),則 「首次有效渲染」須要這個圖片是可見的狀態。因此,一個渲染若是隻有頁面頭部、導航欄,或加載提示標(如旋轉的圖標)就不是合格的「主要內容」。github
「首次有內容的渲染」(First Contentful Paint)是當一些有內容的東西(如文字、圖像、canvas畫布或SVG)第一次被渲染花的時間。它在UMA和追蹤事件(trace event)中須要用到,而且它能夠做爲「首次有效渲染」時間的近似值,但它常常捕獲沒有意義的渲染,如頭部和導航欄。web
在本文中,咱們提出一個基於佈局¬的方法去近似求「首次有效渲染時間」,它匹配了77%的頁面(總共198個頁面中),關於用戶¬感知到的「首次有效渲染」。算法
隨着頁面加載, 佈局對象逐步被加到佈局樹(layout tree)中。
圖1顯示了當加載谷歌搜索結果頁面時,被逐步加載到佈局樹中的佈局對象的數量。圖2是那個頁面加載的視覺進展過程,從WebPageTest結果中能夠看到。 (完整的WPT網頁測試結果)。chrome
「首次有內容的渲染」(1.577秒時)只有頁面頭部,而且到那個時候60個「佈局對象」被添加到頁面。在1.76 s時,頂部廣告已渲染了一部分,而且「佈局對象」總數是103個。 在大約1.86 s時, 搜索結果出現了, 而且261個「佈局對象」被添加到「佈局樹」中。接下來的渲染(1.907秒時)是「首次有效渲染」。在那以後,剩下的搜索結果和頁腳都出如今了下面那些不可見的區域中。視覺上,頁面的渲染在2.425秒時完成。json
圖1:當加載谷歌搜索結果頁面時,被逐步加載到佈局樹中的佈局對象的數量。canvas
圖2:頁面加載的視覺進展過程 瀏覽器
從這個例子中,你能夠觀察到」佈局對象」數量與頁面加載的「完整性」密切相關。
佈局分析員(LayoutAnalyzer)經過幾個計數器收集有關佈局操做的信息,並釋放他們做爲「追蹤事件」(trace events)。我用這些計數器作實驗而且發現 有大量的 「沒有佈局的佈局對象」(LayoutObjectsThatHadNeverHadLayout)的計數器是「首次有效渲染」的一個很好的參考項。其餘的計數器, 像「尺寸改變的佈局塊」( LayoutBlockSizeChanged)或「全都佈局好了的佈局對象」(TotalLayoutObjectsThatWereLaidOut)都對「首次有效渲染」參考更小。這意味着,按照渲染的重要程度, 新的佈局對象的數量比「從新佈局的佈局對象」的數量(relayouts)更有意義。
因此,這是咱們第一次求的近似的「首次有效渲染時間」:
「首次有效渲染時間 」= 緊跟着「最大布局變化」以後的渲染時間點
「最大布局變化」(Biggest layout change)就是 有着大量 「沒有佈局的佈局對象」 的佈局。
在圖1中, 「最大布局變化」是在1.86秒時, 因此下一個渲染時間點(1.907秒)就是「首次有效渲染時間」。
爲何用「佈局對象」的總數來定義「首次有效渲染時間」呢?例如,咱們能不能定義「首次有效渲染時間」爲 百分之多少的佈局已經完成呢?問題是咱們不能可靠地區分這些東西,當頁面完成時。咱們不但願 根據咱們判斷一個頁面是否加載完成的不一樣, 使得計算的「首次有效渲染時間」也大幅度的不一樣。
這一基本方法比「首次有內容的渲染」獲得更好的結果 (見後文中的「評估單元」),但在許多狀況下它仍然不能檢測到真正有意義的渲染。
如今,存在一些這個基本方法不起做用的典型緣由, 因此咱們要經過添加一些算法 能使咱們即時在這些
狀況下也能顯著地提升精確度。
圖3是http://us.weibo.com/gb頁面在...完整的WebPageTest結果)。
圖4顯示了在頁面加載期間被添加的佈局對象的數量,。「首次有效渲染時間」是6.047 s(當在一堆文本內容出現時),但最大的佈局變化大約是在23.8 s。接下來的渲染(24.25秒時)在視覺上是沒有意義的,由於在23.8 s發生的佈局變化時添加的對象在頁面底部,到了可見區域以外。
圖3: 網站http://us.weibo.com/gb的視覺...
圖4: 頁面加載期間被添加的佈局對象的數量變化圖
咱們該如何阻止這些「低於摺疊的佈局」混淆咱們的度量標準呢? 理論上咱們想要檢查每一個佈局是不是可見的,可是由於咱們又想讓這個變成一個UMA度量標準, 就必須避免佈局期間所帶來的昂貴的計算。因此, 當頁面比屏幕高度長的時候,咱們下降了頁面的佈局。具體來講,咱們使用「佈局意義」來代替「佈局對象的原始數量」,以下:
「佈局意義」( layout significance )= 添加的佈局對象的數量/ max(1,頁面高度/屏幕高度)
例如,在圖4中最大的佈局變化發生的時候(23.8秒),頁面高度是屏幕高度的4.25倍, 因此這個「佈局意義」是佈局對象的數量 除以4.25。圖5顯示的佈局過程與圖4相似,但圖5使用了上面定義的「佈局意義」。如今,最重要的佈局變化是在5.89秒, 就在「首次有效渲染」(6.047秒)以前。
圖 5: 佈局意義(佈局對象數量由頁面高度肯定權重)
圖6是http://www.msn.com/頁面視覺的...完整的WebPageTest結果)。最大的佈局變化是在2.51秒,但下面的截圖沒有文本內容,這是由於網絡字體仍然加載。
圖6: http://www.msn.com/頁面的視覺...
當一個網頁字體在加載時,文本已經佈局了(經過使用後備字體的字體度量(metric)),但文本並無在字體阻塞期間渲染(默認狀況下, 字體阻塞期間是從加載開始的3秒)。一眨眼般快速的(Blink)佈局層並不關心文本是否是可見的, 但因爲文本對於用戶感覺到的加載體驗是很重要的,因此咱們的「首次有效渲染」度量標準應把頁面字體的可見性考慮進去。
因此咱們引入算法:若是當佈局發生時還存在加載中的字體,佈局的變化統計將會被推遲,直到該字體顯示出來。(若是三秒內加載了就用該字體,不然超時了就用備用字體顯示)。
可是,把這條規則應用到全部網站字體顯得太勉強了——較小的字體,如圖標字體並不會阻塞「首次有效渲染時間」。在我實驗的實現中, 超過200個字節的網頁字體纔會阻塞「首次有效渲染時間」。
● 這個測量只是基於新的佈局對象,不考慮已佈局的佈局對象的大小或位置的改變。因此這並不適合「穩定的佈局」(layout stabilized)的度量標準。
● 對於一些頁面, 「首次有效渲染」的關鍵因素是圖片。對於等待中的圖片,咱們可能須要一些算法, 就像等待加載的字體用的算法同樣。
● 因爲這個指標是基於佈局對象的,因此這是不受「未鏈接到佈局樹的DOM元素」的影響 (例如display:none的元素)。然而,一些頁面渲染內容在覆蓋物之下, (例如,www.flipkart.com的啓動頁面),或在一個透明層之上(例如www.adobe.com)去實現一個fadein的加載效果。在這些狀況下,咱們的方法發現佈局變化對用戶來講是看不見的, 並且計時是毫無心義的。
● 頁面高度算法使這個度量標準依賴於屏幕的大小。這是很正常的,由於咱們的興趣在是摺疊渲染區域之上的部分, 但推導這個度量標準可能有點複雜。
爲了評估這個方法, 我使用修補版的ChromeAPK,已經在200個熱門網站(基於alexa¬-top,包括子頁面)上跑了WPT測試。而後我下載WPT 的trace.json文件,而且經過運行跟蹤事件來計算上文中提到的基於佈局的「首次有效渲染時間」。WPT還生成截圖幻燈片,因此咱們能夠比較計算的「首次有效渲染時間」和人爲選擇的「用戶感覺到的首次有效渲染時間」的區別。
結果: https://docs.google.com/sprea...r7AdPzmt0aAufMsnnk/ edit?usp=sharing
截屏 (橙色高亮的是檢測到的「首次有效渲染時間」): https://goo.gl/wOHl2s
表1總結告終果。「首次有內容的渲染」是咱們目前有的最好的近似值,並且在52.5%的例子(標註1)中,它匹配了「用戶¬感知的首次有效渲染時間」。不包括「頁面高度算法」或「字體算法」的基本的佈局對象的計數略優於「首次有內容的渲染」 (57.1%)。混合「頁面高度」和「網頁字體」這兩個算法的計算使「首次有效渲染時間」已經達到了77.3%的準確率。
(標註1)在之前的評估中,咱們使用了寬鬆定義的「首次有效渲染」(在屏幕上的可讀部分)。如今咱們使用更嚴格的定義¬——¬頁面的主要內容必須是易讀的。
表1:評估結果的總結
實驗的實現包括了:(1)一個「瞬間的改變」(a Blink side change),這個改變 加強了佈局分析者(LayoutAnalyzer)對頁面高度和網頁字體可見性信息的跟蹤事件;(2)一個腳本 ,該腳本處理跟蹤事件去計算最大的佈局變化。這個實現能夠很容易去把這個變成一個TBMv2度量標準(metrics),而這個標準可用於像Page Cycler V2同樣的基準。
[過期了,請看 UMA design doc(UMA設計文檔)]
咱們但願去收集「首次有效渲染時間」做爲一個UMA度量標準。Finch和heartbeat依賴於UMA, UMA是惟一咱們有的能理解真實用戶體驗的系統。
LayoutAnalyzer默認狀況下是禁用的,由於它有一些計算開銷。咱們不須要全部的LayoutAnalyzer計數器來計算「首次有效渲染時間」, 只須要被添加到佈局樹的佈局對象的數量,這個數量能夠以不一樣的方式收集。
實現計劃:PaintTiming持有一個渲染的時間戳,這個時間戳目前在最大的佈局變化以後。當有更重要的佈局變化時,時間戳會更新。這個時間戳會被髮送到瀏覽器進程的PageLoadMetrics中,而且當用戶從頁面導航出去時它會做爲UMA直方圖。
注意, 「首次有效渲染時間」的時間戳能夠在頁面加載期間更改幾回。若是頁面加載在完成以前失敗, 「頁面加載度量標準」將報告暫時的時間,這個時間可能不是頗有意義,例如導航欄或旋轉圖標。頁面加載度量標準」 在單獨的直方圖裏記錄「失敗的導航欄」的時間 (「頁面加載失敗時間」 *)。對於失敗的頁面加載,咱們須要很是當心地解讀它的「首次有效渲染時間」度量標準。
第一步 (基於跟蹤¬的實現) 來了, 而且它和一個TBMv2 metric(TBMv2標準)同樣,是可得到的.。如今,你能夠從跟蹤觀察器來看「首次有效渲染時間」。
爲了使用這個,你能夠去chrome://tracing並記錄一個激活了如下內容的跟蹤:
● blink.user_timing
● loading
「首次有效渲染時間」的值能夠在「度量標準」側板中看到
(見下圖)。
另外,這些標準能夠從一個跟蹤文件裏計算獲得,經過使用
這個命令:
chromium/src$ third_party/catapult/tracing/bin/run_metric trace.json loadingMetric
第二步 (UMA): 第一個版本的UMA來了。目前, 直方圖是做爲實驗的標記內容,在促進他們的實驗以前,咱們想作一些改進。(跟蹤在https://crbug.com/632081).
引用
"Is it useful?" metric (aka. First meaningful paint): layoutbased approach loadingdev thread implementation tracking bug