web性能入門

高性能瀏覽器網絡 --> 第三部分 HTTP --> 第十章 web性能入門


在一個複雜系統中,性能優化過程主要在於弄明白系統的獨立子系統和層次之間的交互,它們各自都有自己的一系列限制和侷限因素。之前,我們已經分別詳細探討了許多網絡組件 -- 不同的物理傳輸方法和傳輸協議 -- 現在我們可以把我們的注意力轉到更大的,web性能優化的端到端層面。
  • 延遲和帶寬對web性能的影響
  • TCP對HTTP的限制
  • HTTP協議本身的特點和不足
  • Web應用的發展趨勢和性能要求
  • 瀏覽器的限制和優化
不同層次交互的優化不像解方程,有固定的解,每一個層次都彼此依賴,存在很多可能的解決方案。沒有確切的建議,也沒確切的最佳實踐,每個組件都在不斷進化:瀏覽器變得越來越快,用戶的連接配置也在不斷改變,web應用也再不斷擴展,變得更強大更復雜。
因此,在我們開始列舉和分析各個性能最佳實踐之前,退後一步並定義真正的問題是很重要的:現代web應用是怎麼樣的?有什麼工具可以利用?如何測量web性能,哪一部分有助於性能提升,哪一部分又拖後腿?

超文本,網頁,Web應用

在過去的幾十年中,互聯網的發展給了我們至少三種不同類別的體驗:超文本,富媒體網頁,交互式Web應用。不可否認,用戶很難區分後面兩者,不過從性能的角度來講,我們同它們的對話方式,對它們的度量維度,性能的定義是不同的。


超文本文檔

超文本是萬維網的起源,普通文本加上一些基本的格式以及對超鏈接的支持。以今天的標準來看,這些不算什麼,但它證明了,萬維網的遠見,以及它的偉大功能。


網頁

HTML工作組和早期的瀏覽器廠商擴展了超文本定義,以支持額外的超媒體資源,比如圖片,聲音,增加了很多其它原語以支持更豐富的佈局。網頁的時代已經到來了,現在可以使用各種類型的媒體來產生視覺效果更豐富的佈局:看起來很漂亮但大多不具有交互性。


web應用

JavaScript, 動態HTML,以及AJAX這些技術再次帶來革新,使簡單的網頁變成交互性的web應用,它們能夠在瀏覽器中對用戶直接做出反應。這爲第一個成熟的瀏覽器應用鋪平了道路,比如Outlook Web Access , 迎來的腳本,樣式表和標記複雜的依賴關係圖的新時代。


一個HTTP 0.9會話只有一個文檔請求,這對於交付單文檔的超文本完全足夠了,創建TCP連接,請求-響應,然後關閉連接。挖掘性能就是簡單的優化短TCP連接上的單個HTTP請求。
網頁的出現改變了交付模式,從單文檔轉變爲交付文檔加上獨立子資源。因此,HTTP 1.0引入了HTTP元數據的概念(頭,headers),而且使用多種性能導向原語對其進行增強,例如定義明確的緩存,keepalive等原語。現在,可能會同時使用多個TCP連接,關鍵性能度量已經不再是文檔加載時間,而是網頁加載時間,通常稱之爲PLT。

最簡單的PLT的定義:瀏覽器中的加載指示器指明加載完成爲止的時間。一個更偏技術上的定義是瀏覽器中觸發onload事件的時間,這是當文檔和所有獨立子資源(Javascript, 圖片等等)都加載完成時由瀏覽器觸發的事件。

最後,web應用把簡單的網頁,轉換爲複雜的依賴關係圖:標記定義基本的結構,樣式表定義佈局,腳本創建交互式應用並對用戶輸入做出響應,還可能更改樣式和標記。

因此,網頁加載時間,已經成爲web性能事實上的標準,不過,它也是個越來越不充分的性能基準:我們不再創建網頁,我們是在創建動態交互式web應用。現在,除了關心,甚至不在關心,如何測量加載每個資源的時間(PLT),還着重考慮與應用相關的問題:
  • 應用加載進度的里程碑是什麼?
  • 什麼時候發生第一次用戶交互?
  • 用戶應該參與哪些交互?
  • 用戶的參與度和轉化率?
你的性能優化策略是否卓有成效,就看你定義和迭代應用相關的基準和準則的能力了。應用相關的知識和測量是相當重要的,特別是事關你的底線目標和業務指標時。

DOM, CSSOM, and JavaScript

現代web應用中,複雜的腳本、樣式表、和標記依賴關係圖到底是什麼意思呢?爲了回答這個問題,我們需要快速瀏覽一下瀏覽器的架構,看看解析、排版、腳本這些流水線是怎麼配合工作,把一個個像素繪製在屏幕上的。



解析HTML文檔就是構建DOM(Document Object Model)樹。CSS對象模型(CSS Object Model),就像另一個容易被人遺忘的表親,也在並行構建。之後,這兩者被結合起來,用於創建“渲染樹”,接下來,瀏覽器有了足夠的信息進行排版和繪製。自此,一切順利。

然而, 不幸的是,這裏我們必須介紹我們最喜歡的朋友,同時也是敵人: JavaScript。腳本的執行會產生同步doc.write操作並阻塞DOM解析和構建。類似的,腳本可能查詢任何對象以計算它的樣式。這意味着JavaScritpt也會阻塞CSS。因此,DOM對象和CSDOM對象的構建通常交織在一起:DOM構建無法繼續,除非JavaScript執行完成,在CSSOM可用之前,JavaScript無法繼續執行。

你的應用的性能,特別是首次加載和“呈現時間”直接與腳本、標記、樣式表之間的依賴關係相關。順便說一句,記得流行的“風格在頂部,腳本在底部”最佳實踐嗎?現在你知道爲什麼了!渲染和腳本執行被阻塞在樣式表上;儘可能快的把樣式呈現給用戶。


現代web應用剖析


一個現代web應用究竟是啥樣的?HTTP Archive能夠幫助我們回答這個問題。該項目通過定期爬行top流行網站,記錄並彙總分析,每個目標所用資源的數量,類容類型,頭部等其它元數據,來跟蹤Web的創建。
早在2013年,一個web應用的平均構成如下:
  • 90個請求,從15個主機獲取數據,總的傳輸大小爲1,311KB的數據
  • HTML: 10個請求,52KB
  • 圖片:55個請求,812KB
  • JavaScript: 15個請求,216KB 
  • CSS:5個請求, 36KB
  • 其它:5個請求,195KB
在你讀到這裏的時候,前面這些數字可能都已經改變,變的更大了(Figure 10-2)。趨勢是穩步攀升而且沒有停下來的明顯標誌。然而,先不談確切的請求數和千字節數,這些各個組件組成的數量值得我們思量思量:現在web應用平均已經超過了1MB,而且大於有來自15個主機的100個子資源構成。

不像桌面應用,web應用不需要獨立的安裝過程:鍵入URL,點擊Enter,就會啓動並運行!不過,桌面應用只付出一次安裝成本,而web應用在每次訪問時都要執行“安裝過程”-- 下載資源,DOM和CSSOM構建,執行JavaScript。這也難怪web性能是一個發展如此迅速的領域,而且是個熱門話題!幾百個資源,數M數據,10多個不同的主機,所有這些都必須在幾百毫秒內一起完成,以提供期望的即時web體驗。

速度,性能,用戶感知

速度和性能是相對的。每一個應用都會基於商業準則、應用環境、用戶期望、需要執行的任務的複雜性來制定它的一系列需求。話雖如此,如果一個應用必須與用戶進行交互,那麼我們就必須規劃和設計具體的,以用戶爲中心的感性處理時間常數。儘管生活節奏加快了,或者至少感覺如此,但我們反應時間卻不會變化(表10-1),這與應用(在線或離線),或介質(筆記本電腦、臺式機、或手機)的類型無關。

前面這張表解釋了web性能設計的非官方經驗法則:爲了留住用戶,應該在250毫秒內,呈現網頁,或者至少提供點可見的反饋。


想要提供即時體驗的應用,必須在幾百毫秒內對用戶輸入提供能夠感知到的響應。超過1秒,用戶的注意力就會轉移,10秒之後,除非有進度顯示,否則任務就會被拋棄。
DNS查詢,TCP握手,以及一個典型的網頁請求帶來的幾個往返延遲,合計起來很容易就在網絡開銷上花掉100 - 1000毫秒。看Figure 8-2. 這也難怪那麼多用戶,特別是移動網絡和無線網絡用戶,都抱怨網頁瀏覽慢!

Web性能帶來經濟效益
速度是一項功能,不是簡單的爲了速度而追求速度。Google, Microsoft, Amazon廣爲認知的研究顯示web性能可以直接轉化爲經濟效益 -- 例如:Bing搜索頁面上2000ms的延遲將使每用戶收益減少4.3%。
類似的,Aberdeen對160個組織的研究表明網頁加載時間延遲1秒將導致轉化率減少7%,訪問量減少11%,用戶滿意度降低16%!
更快的網站會帶來更多的頁面訪問量、更高的參與度和轉化率。不過,不要把這奉爲圭皋,也不要以爲公認的工業基準就沒有錯:要實際測量你的網站上性能帶來的影響,對比你自己的轉化目標。後面章節會將到怎麼樣測量。

分析資源瀑布

沒有提到資源瀑布的性能討論是不完整的。實際上,資源瀑布很可能是我們掌握最有見地的網絡性能和診斷工具。每個瀏覽器都提供了一些查看資源瀑布的工具,也有一些偉大的在線工具,比如WebPageTest,它能夠爲各種各樣的瀏覽器提供資源瀑布。

WebPageTest.org是一個開源項目,也是一項免費的web服務,它提供了一個用於測試網頁性能的系統,有位於全球範圍內多個地方的多臺主機組成:瀏覽器運行在一個虛擬機上,而且是可配置的,

開始之前,有一點很重要,我們應該認識到,每個HTTP請求可以分爲幾個獨立的階段(Figure 10-3):DNS解析,TCP握手, TLS協商(如果需要),HTTP請求調度,接着是下載網頁內容。這些各個階段的可視化顯示可能因瀏覽器而異(顏色),不過爲了簡單點,我們將在本章使用WebPageTest版本。你應該要很熟悉最喜歡的瀏覽器的各種顏色表示的意義。

仔細分析Figure 10-3,我們會發現下載Yahoo主頁共花費了683ms,等待網絡的時間超過了200ms,佔到了請求總延時的30%!然而,文檔請求僅僅只是個開始,我們知道,一個現代web應用還需要各種各樣的資源(Figure 10-4)才能產生最終的輸出。以加載Yahoo主頁爲例,瀏覽器將需要從30個不同的主機獲取52個資源,總計482KB。
資源瀑布揭示了許多關於網頁結構和瀏覽器處理流水線的重要的洞見。首先,我們注意到,當獲取www.yahoo.com文檔的內容的同時,新的HTTP請求被調度:HTML解析逐步進行,是瀏覽器可以提早發現需要的資源,並在需要是並行調度請求。因此,資源獲取的順序很大程度取決於標記的結構。瀏覽器可能優化一些請求,但是正是對文檔中資源的逐步發現造就了不同資源的“瀑布效應”。
其次,注意“開始渲染”(綠色垂直線)發生在所有資源加載完成之前,以允許用戶在網頁創建的同時就可以開始同它進行交互。事實上,“文檔完成”事件(藍色豎線),也是在所有資源加載完成之前觸發的。換句話說,瀏覽器加載指示器已經停止旋轉,用戶可以繼續他的任務,但Yahoo!主頁還在後臺逐步填充其它內容,比如廣告和社交小工具。

當討論不同的網絡性能指標時,前述例子中,首次渲染時間、文檔完成時間、獲取完最後一個資源的時間的不同很好的說明了上下文的重要性。我們應該跟蹤這三個指標中的哪一個纔對呢?沒有一個單一的答案;要看應用!Yahoo!的工程師選擇了優化網頁,以利用逐步加載,從而使用戶可以早點看到重要的內容,要這樣做,他們必須應用應用相關的知識,哪些內容是關鍵的,哪些可以放後點。

何時,以怎樣的順序調度資源?不同的瀏覽器實現的邏輯是不一樣的。所以,應用的性能在不同的瀏覽器之間差異很大。
提示:WebPageTest 允許你選擇用於執行測試的瀏覽器版本,以及測試位置。

網絡訪問瀑布是一個強大的工具,可以幫助我們檢查對網頁和應用的優化的效果,以及應該優化的方面。前面討論的分析和優化資源瀑布的過程常常稱之爲前端性能(front-end performance)分析和優化。然而,這個名字可能是個不幸的選擇,因爲它會誤導很多人,使他們相信所有性能瓶頸都在客戶端。現實中,JavaScript, CSS,以及渲染流水線都是資源密集型步驟,服務器響應時間和網絡延遲("後端性能")對於優化資源瀑布相對不重要。畢竟,你不能解析和執行一個被阻塞在網絡上的資源。
爲了說明這個問題,我們只需要在WebPageTest上從resource waterfall view切換到connection view(Figure 10-5)。
在resource waterfall view中,每一條記錄代表一個單一的HTTP請求,connection view 與此不同,每一條記錄代表一個TCP連接的生命週期 -- 該例子中總共有30個TCP連接 -- 用於從Yahoo!主頁獲取資源。有什麼特別之處嗎?注意下載時間,藍色表示的部分,只佔了每個連接總延遲的一小部分:15個DNS查詢,30個TCP握手,以及在等待接收每個響應的第一個字節時的很多網絡延遲(綠色部分) -- 大部分的延遲是由這些部分組成。

很奇怪爲什麼有的請求只有綠色條(time to first byte)?很多響應都很小,下載時間可以忽略不計,因此就沒有顯示在圖上。實際上,對很多請求而言,響應時間常常是由往返時間和服務器處理時間組成。

最後,我們把最好的留在了最後。真正的驚喜在the connection view的底部:檢查Figure 10-5 中的帶寬利用率圖表。除了幾個數據突發點,網絡利用率是很低的 -- 看起來連接帶寬並沒有給我們帶來限制!這是異常情況嗎?還是個瀏覽器的bug?不幸的是,這兩者都不是。結果證明,對於大多數web應用而言,帶寬不是性能限制因素。相反,瓶頸是客戶端和服務器之間的網絡往返延遲。

性能支柱:計算, 渲染, 網絡

一個web程序的執行首先涉及到三個任務:獲取資源,網頁佈局和渲染,還有JavaScript執行。渲染和腳本執行步驟遵從單線程,交錯執行模型。不能對產生的DOM執行併發修改。因此,優化和協調好渲染和腳本執行是極其重要的。
不過,如果瀏覽器被阻塞在網絡,等待着資源到來,那優化腳本執行和渲染流水線也沒多大用處。網絡資源的快速而高效的交付是運行在瀏覽器中的每一個應用的性能基石。
但是,有人可能會問了,網絡速度正在一天比一天快,所以這個問題不會自行解決嗎?是的,我們的應用在不斷變大,但是假如全球平均網速已經達到3.1Mbps而且在不斷增長,正如每一個ISP和運營商廣而宣傳的那樣,我們還用擔心這個問題嗎?不幸的是,你可能直覺上也知道,而且Yahoo!這個例子也說明,如果答案是“是”,那我們也不會再讀這本書了。讓我們來仔細看看。

更多的帶寬作用不大

彆着急;帶寬當然是很重要的!畢竟,每一個本地ISP和移動運營商都在不斷的提醒我們高帶寬的諸多好處:更快的下載、上行、和流速度,速度可達【插入最近的數字】Mbps!
更高的帶寬數據速率總是有好處的,特別是涉及大量數據傳輸的情況:視頻和音頻流,或者其它任何類型的大數據傳輸。然而,日常的網頁瀏覽,需要從幾十個主機上獲取上百個相對較小的資源,往返時間就成了限制因素:
  • 觀看Yahoo!主頁上的高清視頻受帶寬限制
  • 加載和渲染Yahoo!主頁受往返延遲所限
取決於你想要觀看的視頻的質量和編碼,你可能需要幾百Kbps到幾Mbps的帶寬容量 -- 例如,HD 1080p視頻需要3+Mbps帶寬容量。現在很多用戶都可以達到這個速率,流視頻服務,比如Netflix日漸流行也證實了這一點。那麼,爲何對於一個能夠支持HD視頻流的連接而言下載一個要小得多的web應用會是一個挑戰呢?

性能瓶頸 -- 延遲

在前面的章節中,我們已經討論了所有必需的主題,以爲爲什麼延遲是日常網頁瀏覽的限制因素打下良好的理論基礎。然而,一張圖勝過千言萬語,我們來看由Mike Belshe,SPDY協議的創建者之一,所做的一個定量研究的結果(Figure 10-6),關於帶寬變化和延遲變化對某些流行網頁的網頁加載時間的影響。


Mike Belshe所做的研究成爲了Google開發SPDY協議的啓動點,SPDY後來成爲了HTTP 2.0的基礎。

在第一個測試中,連接延遲固定不變,連接的帶寬從1Mbps逐步增加到10Mbps。可以看到,一開始連接帶寬從1Mbps升到2Mbps幾乎是網頁加載時間縮短了一半 -- 正是我們想看到的結果。然而,接下來,帶寬的提升產生了收益遞減。當帶寬超過5Mbps時,就只有個位數百分比的改進了,帶寬從5Mbps升到10Mbps,對網頁加載時間的改進僅僅只有5%。
Akamai's寬帶速度報告(“Bandwidth at the Network Edge”)顯示,美國用戶的平均帶寬已經超過了5Mbps -- 很多國家也將達到這個數字,還有很多國家已經超越了這個數字。因此,可以推斷,一個美國的平均消費者,假如他想要提升web瀏覽速度,通過升級帶寬是收效甚微的。他可以更快的下載和上傳大視頻文件,但包含這些文件的網頁的加載並不會顯著變快:帶寬作用不大。
然而,延遲實驗情況就不同了:延遲每改進20毫秒,網頁加載時間都有一個線性的提升!或許當我選擇ISP時也應該考慮延遲,而不僅僅是帶寬。

爲了大大加快網絡訪問速度,我們應該尋找更多降低RTT的方式。如果我們能夠把跨越大西洋的RTTs從150ms降到100ms會有什麼效果?這對網絡訪問速度的改進效果比把帶寬從3.9Mbps提升至10Mbps甚至1Gbps效果還明顯。
另一個降低網頁加載時間的方法是減少每次加載所需要的往返次數。如今,網頁需要的服務器和客戶端之間的往返次數通常都是固定的。往返次數大部分在於握手到開始服務器與客戶端通信(eg, DNS, TCP, HTTP),還有有通信協議引入的往返(例如,TCP慢啓動)。如果我們能夠改進協議以更少的往返次數來傳輸這些數據,我們應該就可以改進網頁加載時間。這是SPDY協議的目標之一。
                                                                                                                                                                                              -- Mike Belshe More Bandwidth Doesn't Matter (Much)
前面的結果可能令很多人感到驚訝,不過你應該想到的,因爲它們是底層協議性能特徵的直接結果:TCP握手,流控制和擁塞控制,丟包造成的線段阻塞(head-of-line blocking)。大部分HTTP速率流有小的,突發數據傳輸構成,然而TCP是優化用於長連接和塊(bulk)數據傳輸的。大部分情況下,網絡往返時間(RTT)是TCP吞吐量和性能的限制因素。因此,延遲也是HTTP和其它使用TCP的應用的性能瓶頸。

如果網絡時大部分有線連接的性能限制因素,你可能直覺的意識到,它應該是無線客戶端更重要的性能瓶頸:無線網絡延遲非常高,所以移動web的網絡優化優先級更高。

瀏覽器優化

現代瀏覽器可不是個簡單的網絡socket管理器,如果我們沒有提到這一點,我們就失職了。性能是每一個瀏覽器廠商最主要的競爭功能之一,鑑於網絡性能是如此關鍵,瀏覽器正在日益變得更智能:DNS預解析,預連接可能的目標,預期和優化網頁上的關鍵資源,等等,對此,你應該不會感到驚訝。
每個瀏覽器廠商的確切的優化列表可能不同,但他們優化的核心都可以分爲兩個大類:
文檔感知優化
網絡棧集成了文檔、CSS、JavaScript解析流水線以幫助識別關鍵網絡資源並進行優先級劃分,進行提早調度,使網頁儘可能快的進入交互狀態。這通常是通過給資源分配優先級,預讀解析,還有一些類似的技術實現的。
預測優化
隨着時間的推移,瀏覽器可以學習用戶的瀏覽模式,並執行預測優化以嘗試推測可能的用戶行爲。這樣的優化包括預解析DNS,預連接可能的主機,等等
好消息是這些優化都由瀏覽器自動完成的,而且常常能夠減少幾百毫秒的網絡延遲。但話說回來,理解爲什麼要做這些優化,以及這些優化的工作原理是很重要的,因爲我們可以協助瀏覽器以幫助它加速我們的應用。大多數瀏覽器都使用四種技術:

資源預取和優化
文檔,CSS,以及JavaScript解析能夠給網絡棧額外的信息以指明每個資源的相對優先級:會阻塞第一次渲染的資源被給予高優先級,同時,低優先級的請求可能被臨時放在隊列尾部。
DNS預解析
提前解析可能訪問的主機名以爲將來的一個HTTP請求避免DNS延遲。預解析的可以通過學習瀏覽歷史觸發,用戶的動作比如鼠標懸停在一個鏈接上,或網頁上的其它信號都可能觸發預解析。
TCP預連接
DNS解析之後,瀏覽器可能根據推測打開一個TCP連接。如果猜對了,它就能消除另一個完整的網絡往返延遲。
網頁預渲染
有的瀏覽器允許你提示它下一個可能的目標,它能夠在隱藏tab中渲染整個網頁,如此,當用戶發起瀏覽時,網頁就能立即呈現。

想要深入瞭解Google Chrome是如何實現這些優化的,可以看High Performance Networking in Google Chrome

從外部看,現代瀏覽器的網絡棧是個簡單的資源獲取裝置,但在內部,它是一個研究如何優化web性能的精彩世界。我們怎樣協助瀏覽器呢?首先,我們應該密切注意每個網頁的結構和交付:
  • 關鍵資源,比如CSS和JavaScript應該能夠儘快被發現
  • CSS應該儘早交付以避免阻塞渲染和腳本執行
  • 不重要的JavaScript應該被推遲以避免阻塞DOM和CSSOM構建
  • 解析器逐步解析HTML文檔;因此爲了最好的性能,文檔應該被定期刷新。
此外,除了優化網頁結構,我們還可以在文檔中嵌入額外的提示,暗中告訴瀏覽器替我們執行某些優化:
<link rel="dns-prefetch" href="//hostname_to_resolve.com"> 1
<link rel="subresource"  href="/javascript/myapp.js"> 2
<link rel="prefetch"     href="/images/big.jpeg"> 3
<link rel="prerender"    href="//example.org/next_page.html"> 4
1 域解析指定主機名
2 預取關鍵資源
3 預取資源
4 預渲染指定網頁
這些都是預測優化的提示。瀏覽器不保證執行,但它可以利用這些提示優化它的加載策略。不幸的是,並不是所有的瀏覽器都支持所有的提示(Table 10-2)


爲Google Search 優化Time to First Byte(TTFB)
HTML是由瀏覽器逐步解析的,這意味着服務器能夠頻繁的刷新文檔標記,也應該這麼做。這樣客戶端可以儘快發現並獲取關鍵資源。
Google Search是一個關於這種技術的益處的一個最好的例子:當一個搜索請求到來時,服務器立即刷新搜索頁面的靜態頭,然後纔去分析查詢。畢竟,爲什麼要等呢,每一個搜索頁面的頭部都是一樣的!然後,當客戶端解析頭部標記時,搜索查詢被分派給搜索索引,一旦搜索結果準備好,文檔的餘下部分,包括搜索結果,就被髮送給用戶。至於網頁頭的動態部分,比如登陸用戶的名字,是通過JavaScript填充的。


原文:http://chimera.labs.oreilly.com/books/1230000000545/ch10.html#BROWSER_OPTIMIZATION

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章