在谷歌瀏覽器隨便打開一個頁面,點擊「選項」菜單,選擇「更多工具」,點擊「任務管理器」,這將打開Chrome的任務管理器的窗口,你會發現一個頁面上有四個以上的進程。爲何會有四個進程呢? 本章經過分析瀏覽器的進化史而展開探討這個問題。
開始以前,咱們必須得了解一下這個進程
與線程
的概念。html
線程這個東西它是不能單獨存在的,它是由進程來啓動和管理的。
web
一個進程就是一個程序的運行實例
。算法
線程是依附於進程的,而進程中使用多線程並行處理能提高運算效率
。瀏覽器總結,線程與進程之間的關係有如下四個特色:緩存
- 進程中任一線程執行出錯,都會致使整個進程崩潰。
- 線程之間共享進程的數據。
- 當一個進程關閉以後,操做系統會回收進程所佔用的內存。
- 進程之間的內容都互相隔離。(若是進程之間須要進行數據的通訊,這時候須要使用用於進程間通信(IPC)機制了)。
早在07年以前,市面上的瀏覽器都是單進程的。單進程,顧名思義是指:瀏覽器的全部功能模塊都運行在同一個進程裏。
如此多的功能模塊運行在一個進程裏,致使單進程瀏覽器不穩定
、不流暢
、不安全
。
具體的表現就不說了,總之體驗很是差,因而進入了「多線程瀏覽器」時代。安全
- 多進程瀏覽器因爲進程相互隔離,因此當一個頁面或者插件崩潰的時候,影響的僅僅是當前的頁面進程或者插件過程。這就完美解決了頁面或者插件崩潰而致使的整個瀏覽器崩潰問題。JS的渲染若出現問題,影響的一樣是當前的渲染頁面,沒有響應的僅對當前頁面。並且在多進程瀏覽器時代,當關閉一個頁面的時候,整個渲染進程會被關閉,該進程佔用的內存都會被系統回收,這樣也就輕鬆解決了瀏覽器頁面的內存泄露問題。
- 此外有關安全方面的問題:使用多線程架構可使用
安全沙箱
。能夠把沙箱當作是操做系統給進程上了一把鎖,沙箱裏面的程序能夠運行,可是不能在硬盤上寫入任何數據,也不能在敏感位置讀取任何數據(例如文檔和桌面),Chrome把插件進程和渲染進程鎖在沙箱裏面,這樣即便在渲染進程或者插件進程裏面執行了惡意程序,惡意程序也沒法突破沙箱去獲取系統權限。服務器
最新的Chrome進程架構:Chrome瀏覽器包括:
1個瀏覽器(Brower)主進程,1個GPU進程、一個網絡(NetWork)進程、多個渲染進程和多個插件進程
。
雖然多進程模型提高了瀏覽器的穩定性、流暢性、安全性,可是一樣也會不可避免帶來一些問題:微信
更高的資源佔用
:由於每一個進程都會包含公共基礎結構的副本(如JavaScript運行環境),這意味着瀏覽器會消耗更多的資源。更復雜的體系架構
:瀏覽器各模塊之間耦合性高、擴展性差等問題,會致使如今的架構已經很難適應新的需求。
爲了解決這些問題,2016年,Chrome團隊使用「面向服務的架構「(SOP)思想設計了新的Chrome架構,這也是現階段Chrome團隊的一個主要任務。網絡
在衡量Web頁面性能的時候有一個重要的指標叫"FP(First Paint)",是指從頁面加載到首次開始繪製的時長。其中影響FP的一個重要因素就是
網絡加載速度
。數據結構要優化網絡加載速度,須要對網絡有充分的瞭解,這一節重點介紹
在Web世界中的TCP/IP是如何工做的
。在網絡中,一個文件一般會被拆分爲不少數據包來進行傳輸,而數據包在傳輸過程當中有很大概覽丟失或者出錯,那麼如何保證頁面文件能被完整地送達瀏覽器?
IP:把數據包送達目的主機
計算機的地址稱爲IP地址,訪問任何網站實際上只是你的計算機向另一臺計算機請求信息。
當從主機A向主機B發送數據(即發送數據包),傳輸前,數據包會被附加上主機A和主機B的IP地址信息,這些信息會被封到一個叫作IP頭的數據結構裏,在這個IP頭中包含IP數據包開頭的信息(IP版本、源IP地址、目標地址、生存時間等信息),因而數據包從主機A發送到主機B。UDP:把數據包送達應用程序 IP經過IP地址信息把數據包發送給指定的電腦,而UDP經過端口號把數據包發給正確的程序。 UDP發送數據,有各類因素會致使數據包出錯,雖然UDP能夠校驗數據是否正確,可是
UDP不提供重發機制
,只是丟棄當前的包,且UDP在發送以後沒法知道可否到達目的地。
UDP不能保證數據可靠性,可是傳輸速度卻很是快
,所以UDP應用在一些關注速度但不那麼嚴格要求數據完整性的領域,例如:在線視頻、互動遊戲等。TCP:把數據完整的送達應用程序 TCP(Transmission Control Protocol,傳輸控制協議):他是一種面向鏈接的、可靠的、基於字節流的傳輸層通訊協議。相對於UDP而言:
- 對於數據包丟失狀況,提供重傳機制。
- TCP引入數據包排序機制,用來保證把亂序的數據包組合成一個完整的文件。
咱們如今已經知道TCP單個數據包的傳輸流程和UDP流程差很少,不一樣在於,經過TCP頭信息能夠保證一塊大的數據傳輸的完整性。 一個完整的TCP鏈接過程,其生命週期包括了「創建鏈接「、」數據傳輸「、」斷開鏈接「三個階段。
- 創建鏈接階段:這個階段經過「三次握手」來創建客戶端和服務器之間的鏈接。
- 數據傳輸階段:在該階段,接收端須要對每一個數據包進行確認操做。接收端應該在接收數據後要發送確認數據包給發送端,若發送端沒有接收到這個確認,則判斷數據包丟失,並觸發發送端的重發機制。
- 斷開鏈接階段:數據傳輸完畢,終止鏈接,經過最後一個階段「四次揮手」來保證雙方都能斷開鏈接。
首先的首先咱們知道:HTTP協議創建在TCP鏈接基礎之上的。
HTTP是一種容許瀏覽器向服務器獲取資源的協議,是Web的基礎。HTTP是瀏覽器使用最廣的協議
。簡單說說HTTP和TCP的關係:瀏覽器使用HTTP協議做爲
應用層協議
,用來封裝請求的文本信息,並使用TCP/IP做爲傳輸層協議
將它發到網路上,因此HTTP工做前,須要經過TCP與服務器創建鏈接,也就是說:HTTP的內容是經過TCP的傳輸數據階段來實現的
。
若是在瀏覽器地址欄裏輸入:www.liugezhou.online 這個網址後,瀏覽器這個龐然大物,它的背後都作些什麼呢?
首先瀏覽器構建請求行信息,構建好以後,瀏覽器準備發起網路請求。
在準備發起網路請求階段,瀏覽器偷偷的在它的緩存中查詢是否有要請求的資源。
如有:攔截請求,返回資源副本,直接結束請求。
若緩存查找失敗:繼續下一步。
這個IP地址和端口號的獲取,確定是經過域名與其映射,即「域名系統」,也就是咱們熟知的DNS。 因而,瀏覽器第一步會請求DNS返回域名對應的IP,若是沒有特別指明端口號,則默認爲80。 (瀏覽器提供了DNS數據緩存服務,若緩存過也就不會去請求,直接解析。從而減小一次網絡請求)
拿到IP地址與端口號後,還須要在TCP隊列中排隊才能創建TCP鏈接。
這是由於:Chrome有個機制,同一個域名同時最多隻能創建6個TCP鏈接,若此刻同時有10個請求發生。則四個會進入TCP隊列進行排隊。 固然,若當前請求數量少於6個,則會直接進入下一步。
創建TCP鏈接,上一節咱們已經知道,一個完整的TCP鏈接過程包括「創建鏈接」、「數據傳輸」、「斷開鏈接「三個階段。
HTTP請求是在TCP鏈接的數據傳輸階段工做的,這個時候瀏覽器向服務器發送請求行,它包括請求方法、請求URI、HTTP版本協議。,HTTP中的數據在這個通訊過程當中傳輸。
這裏能夠在命令行中輸入
curl -i https://www.google.com
來查看返回請求數據。 (-i 返回響應行、響應頭和響應體信息。 -I 不返回響應體。)
返回網站的HTTP協議、Connection、Location、Cache-Control等信息。一般狀況,一旦服務器向客戶端返回了請求數據,它就要關閉TCP鏈接,可是若是瀏覽器或者服務器設置了
Connection:keep-alive
,那麼TCP鏈接在發送後將仍保持打開狀態。保持TCP鏈接能夠省去下次請求時須要創建鏈接的時間,提高資源加載速度
。
主要緣由確定是第一次加載頁面的過程當中,緩存了一些數據(從上面的過程分析,咱們知道
DNS緩存
和頁面資源緩存
這兩塊數據是會被瀏覽器緩存起來的).
網站把不少資源都緩存到了本地,瀏覽器緩存直接使用本地副原本回應請求,而不會產生真實的網絡請求,從而節省了時間。
簡單地說,若是服務器端發送的響應頭內有 Set-Cookie 的字段,那麼瀏覽器就會將該字段的內容保持到本地。當下次客戶端再往該服務器發送請求時,客戶端會自動在請求頭中加入 Cookie 值後再發送出去。服務器端發現客戶端發送過來的 Cookie 後,會去檢查到底是從哪個客戶端發來的鏈接請求,而後對比服務器上的記錄,最後獲得該用戶的狀態信息。
流程開始前,回顧下瀏覽器進程、網絡進程、渲染進程的各自主要職責:
- 瀏覽器進程:主要負責
用戶交互
、子進程管理
和文件儲存
等功能。- 網絡進程:面向渲染進程或瀏覽器進程提供
網絡資源下載
。- 渲染進程:將HTML、CSS、JS、圖片等資源解析爲能夠顯示和交互的頁面。
- 首先,用戶從瀏覽器進程中輸入請求信息。
- 而後,網絡進程發起URL請求。
- 服務器響應URL請求後,瀏覽器進程開始準備渲染進程。
- 渲染進程準備好之後,須要先向渲染進程提交頁面數據,這稱之爲文檔提交階段。
- 渲染進程接收到文檔信息以後,便開始解析頁面和加載子資源,完成頁面的渲染。 這其中,用戶發出URL請求到頁面開始解析的過程,就叫作導航。
- 響應數據類型處理:根據服務端返回的
Content-Type
字段來決定如何顯示響應體的內容。- 同一站點下的多個頁面會運行在一個渲染進程中。
- 用戶輸入url並回車·
- 瀏覽器進程檢查url,組裝協議,構成完整的url
- 瀏覽器進程經過進程間通訊(IPC)把url請求發送給網絡進程
- 網絡進程接收到url請求後檢查本地緩存是否緩存了該請求資源,若是有則將該資源返回給瀏覽器進程
- 若是沒有,網絡進程向web服務器發起http請求(網絡請求),請求流程以下: 5.1 進行DNS解析,獲取服務器ip地址,端口 5.2 利用ip地址和服務器創建tcp鏈接 5.3 構建請求頭信息 5.4 發送請求頭信息 5.5 服務器響應後,網絡進程接收響應頭和響應信息,並解析響應內容
- 網絡進程解析響應流程; 6.1 檢查狀態碼,若是是301/302,則須要重定向,從Location自動中讀取地址,從新進行第4步
6.2 200響應處理: 檢查響應類型Content-Type,若是是字節流類型,則將該請求提交給下載管理器,該導航流程結束,再也不進行後續的渲染,若是是html則通知瀏覽器進程準備渲染進程準備進行渲染。- 準備渲染進程 7.1 瀏覽器進程檢查當前url是否和以前打開的渲染進程根域名是否相同,若是相同,則複用原來的進程,若是不一樣,則開啓新的渲染進程
- 傳輸數據、更新狀態 8.1 渲染進程準備好後,瀏覽器向渲染進程發起「提交文檔」的消息,渲染進程接收到消息和網絡進程創建傳輸數據的「管道」 8.2 渲染進程接收完數據後,向瀏覽器發送「確認提交」 8.3 瀏覽器進程接收到確認消息後更新瀏覽器界面狀態:安全、地址欄url、前進後退的歷史狀態、更新web頁面。
按照渲染的時間順序,渲染流水線可分爲如下幾個構建階段:
構建DOM樹
、樣式計算
、佈局階段
、分層
、繪製
、光柵化
、合成
。 本節主要討論前三個階段。
由於瀏覽器沒法直接理解和使用 HTML,因此須要將 HTML 轉換爲瀏覽器可以理解的結構——DOM 樹。 DOM樹和HTML內容幾乎同樣,但和HTML不一樣的是:DOM是保存在內存中的樹結構。
- 把CSS轉換爲瀏覽器可以理解的結構。
- 轉換樣式表中的屬性值,使其標準化。
「例如rem -> px, red -> rgb(255,0,0),bold -> 700」- 計算出DOM樹中每一個節點的具體樣式。
「CSS繼承:每一個DOM節點都包含有父節點的樣式」
「CSS層疊:它在 CSS 處於核心地位,定義瞭如何合併來自多個源的屬性值的算法」
「樣式來源:若是一個元素不提供任何樣式,默認使用的是UserAgent樣式---瀏覽器提供的一組默認樣式」。
內容: 佈局階段是根據DOM樹和樣式計算出元素的幾何位置。
- 建立佈局樹「構建一顆只包含可見元素的佈局樹」
- 佈局計算
「在執行佈局操做的時候,會把佈局運算的結果從新寫回佈局樹中,因此佈局樹既是輸入內容也是輸出內容,這是佈局階段一個不合理的地方,由於在佈局階段並無清晰地將輸入內容和輸出內容區分開來。針對這個問題,Chrome 團隊正在重構佈局代碼,下一代佈局系統叫
LayoutNG
,試圖更清晰地分離輸入和輸出,從而讓新設計的佈局算法更加簡單。」
爲了生成一些複雜效果(3D變換、頁面滾動、z軸排序等),渲染引擎還須要爲特定的節點生成專用的圖層,生成一顆對應的圖層樹.
- 並非佈局樹的每一個節點都包含一個圖層,若是一個節點沒有對應的層,那麼這個節點就從屬於父節點的圖層.
- 素有了層疊上下文的屬性或者須要被剪裁,知足這任意一點,就會被提高成爲單獨一層。
一個圖層的繪製拆分紅不少小的繪製指令,而後再把這些指令按照順序組成一個
待繪製列表
。「可在瀏覽器開發者工具的Layers中查看。」
所謂柵格化,是指將圖塊轉換爲位圖。
柵格化過程都會使用 GPU 來加速生成,使用 GPU 生成位圖的過程叫快速柵格化,或者 GPU 柵格化,生成的位圖被保存在 GPU 內存中.
一旦全部圖塊都被光柵化,合成線程就會生成一個繪製圖塊的命令——「DrawQuad」,而後將該命令提交給瀏覽器進程。通過瀏覽器就會顯示出頁面。
一個完整的渲染流程大體可總結爲以下:
- 渲染進程將 HTML 內容轉換爲可以讀懂的 DOM 樹結構。
- 渲染引擎將 CSS 樣式錶轉化爲瀏覽器能夠理解的 styleSheets,計算出 DOM 節點的樣式。
- 建立佈局樹,並計算元素的佈局信息。對佈局樹進行分層,並生成分層樹。
- 爲每一個圖層生成繪製列表,並將其提交到合成線程。
- 合成線程將圖層分紅圖塊,並在光柵化線程池中將圖塊轉換成位圖。
- 合成線程發送繪製圖塊命令 DrawQuad 給瀏覽器進程。瀏覽器進程根據 DrawQuad 消息生成頁面,並顯示到顯示器上。
使用CSS或者JS使元素的幾何位置發生了改變,例如改變元素的寬度、高度等,這會使得瀏覽器觸發從新佈局、解析以後的一系列子階段,這個過程就是重排。無疑,重排鬚要更新完整的渲染流水線,因此開銷是最大的。
好比改變了元素的背景色,這會觸發瀏覽器進行重繪以後的操做。相較於重排操做,重繪省去了佈局和分層階段,因此執行效率會比重排操做要高一些。
那若是你更改一個既不要佈局也不要繪製的屬性,會發生什麼變化呢?渲染引擎將跳過佈局和繪製,只執行後續的合成操做,咱們把這個過程叫作合成. 例如CSS的transform實現的動畫效果,能夠避開重排和重繪階段,相對於重繪和重排,合成能大大提高繪製效率。
若有疑問請添加個人微信號:18231133236。歡迎交流!
更多內容,請訪問的個人我的博客:www.liugezhou.online.
您也能夠關注個人我的公衆號:【Dangerous Wakaka】