ZLL的每周一更(maybe)--浏览器的运行机制
ZLL的每周一更
- 介紹
- 瀏覽器分類和介紹
- 瀏覽器的結構
- 瀏覽器中的進程和線程
- 瀏覽器解析流程
- 最后
介紹
你好! 這是ZLL每周一更的第一篇內容,每周我都會整理關于前端的一些知識點,幫助大家(以及我自己,^^)在工作以及求職的路上更加順利,這就是這個系列的開篇啦,在開篇的介紹里面肯定不得已要說多一點。好了,來到正題,這周的內容是瀏覽器的幕后原理,參考了MDN以及Tali Garsiel && Paul Irish編寫的這篇文章,希望能爭取把知識用更好理解的方式展示給各位,那么就開始啦。
瀏覽器分類和介紹
目前使用的主流瀏覽器有五個:Internet Explorer、Firefox、Safari、Chrome 瀏覽器和 Opera。本文中以開放源代碼瀏覽器為例,即 Firefox、Chrome 瀏覽器和 Safari(部分開源)。根據 StatCounter 瀏覽器統計數據,目前(2011 年 8 月)Firefox、Safari 和 Chrome 瀏覽器的總市場占有率將近 60%。由此可見,如今開放源代碼瀏覽器在瀏覽器市場中占據了非常堅實的部分。
瀏覽器的結構
瀏覽器自上至下分為這幾層,分別是
1. 用戶界面 - 包括地址欄、前進/后退按鈕、書簽菜單等。除了瀏覽器主窗口顯示的您請求的頁面外,其他顯示的各個部分都屬于用戶界面。
2. 瀏覽器引擎 - 在用戶界面和呈現引擎之間傳送指令。
3. 呈現引擎 - 負責顯示請求的內容。如果請求的內容是 HTML,它就負責解析 HTML 和 CSS 內容,并將解析后的內容顯示在屏幕上。
4. 網絡 - 用于網絡調用,比如 HTTP 請求。其接口與平臺無關,并為所有平臺提供底層實現。
5. 用戶界面后端 - 用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與平臺無關的通用接口,而在底層使用操作系統的用戶界面方法。
6. JavaScript 解釋器。用于解析和執行 JavaScript 代碼。
7. 數據存儲。這是持久層。瀏覽器需要在硬盤上保存各種數據,例如 Cookie。新的 HTML 規范 (HTML5)定義了“網絡數據庫”,這是一個完整(但是輕便)的瀏覽器內數據庫。
以上是瀏覽器的主要架構,但是和我們日常瀏覽器的使用還是有區別,我們當前所用的瀏覽器(例如谷歌)是多進程的,那么以上瀏覽器結構中哪些是需要開啟多進程哪些是只有一個進程處理的呢,首先我們就得來談談瀏覽器中的進程和線程
瀏覽器中的進程和線程
首先,我們得弄清楚進程和線程的概念
1:進程是一個具有一定獨立功能的程序在一個數據集上的一次動態執行的過程,是操作系統進行資源分配和調度的一個獨立單位
2:線程是擁有資源和獨立運行的最小單位,也是程序執行的最小單位
類似于下圖,簡而言之,進程就相當于一個工廠,線程就相當于工廠中的工人,工廠中的工人(線程)可以共享工廠(進程)中的資源,但是不同工廠(進程)之間不能進行資源共享。
在弄清楚之后,我們就來看看瀏覽器中到底執行了哪些進程和哪些線程
瀏覽器中的進程
1:瀏覽器的主進程(負責協調、主控),只有一個
2:第三方插件進程(每種類型的插件對應一個進程,僅當使用該插件時才創建)
3:GPU進程(最多一個,用于3D繪制)
4:瀏覽器渲染進程 默認每個Tab頁面一個進程,互不影響,控制頁面渲染,腳本執行,事件處理等(有時候會優化,如多個空白tab會合并成一個進程)
(以下圖片中,用戶界面,瀏覽器引擎,網絡層,用戶界面后端都屬于瀏覽器主進程)
渲染進程中的線程
基本上分為以下五大線程
1. GUI渲染線程
(GUI渲染進程與上文的GPU進程不是一個…)
- 負責渲染瀏覽器界面,解析HTML,CSS,構建DOM樹和RenderObject樹,布局和繪制等。
- 當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該線程就會執行
- 注意,GUI渲染線程與JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起(相當于被凍結了),GUI更新會被保存在一個隊列中等到JS引擎空閑時立即被執行。
2. JS引擎線程
-
也稱為JS內核,負責處理Javascript腳本程序。(例如V8引擎)
-
JS引擎線程負責解析Javascript腳本,運行代碼。
-
JS引擎一直等待著任務隊列中任務的到來,然后加以處理,一個Tab頁(renderer進程)中無論什么時候都只有一個JS線程在運行JS程序
-
同樣注意,GUI渲染線程與JS引擎線程是互斥的,所以如果JS執行的時間過長,這樣就會造成頁面的渲染不連貫,導致頁面渲染加載阻塞。
3. 事件線程
-
歸屬于瀏覽器而不是JS引擎,用來控制事件循環(可以理解,JS引擎自己都忙不過來,需要瀏覽器另開線程協助)
-
當JS引擎執行代碼塊如setTimeOut時(也可來自瀏覽器內核的其他線程,如鼠標點擊、AJAX異步請求等),會將對應任務添加到事件線程中
-
當對應的事件符合觸發條件被觸發時,該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理
-
注意,由于JS的單線程關系,所以這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閑時才會去執行)
4. 定時器線程
-
傳說中的setInterval與setTimeout所在線程
-
瀏覽器定時計數器并不是由JavaScript引擎計數的,(因為JavaScript引擎是單線程的,
如果處于阻塞線程狀態就會影響記計時的準確) -
因此通過單獨線程來計時并觸發定時(計時完畢后,添加到事件隊列中,等待JS引擎空閑后執行)
-
注意,W3C在HTML標準中規定,規定要求setTimeout中低于4ms的時間間隔算為4ms。
5. 異步HTTP線程
-
在XMLHttpRequest在連接后是通過瀏覽器新開一個線程請求(通過瀏覽器網絡模塊)
-
將檢測到狀態變更時,如果設置有回調函數,異步線程就產生狀態變更事件,將這個回調再放入事件隊列中。再由JavaScript引擎執行。
瀏覽器解析流程
- 首先,渲染進程通過瀏覽器從網絡層獲取請求文檔內容,然后便開始解析HTML文件,將其中的DOM和CSS文件分別解析成DOM樹和CSS規則樹,然后共同組成渲染樹,(注意DOM樹與渲染樹的節點不一定相同,例如display:none的DOM節點則不會出現在渲染樹中)
- 下一步進入“布局”處理階段,也就是為每個節點分配一個應出現在屏幕上的確切坐標,也就是我們熟知的重排
- 下一個階段是繪制 - 呈現引擎會遍歷呈現樹,由用戶界面后端層將每個節點繪制出來,也就是我們熟知的重繪。
所以很容易理解,重排必定會導致重繪,而重繪不會導致重排。
如圖,這是Webkit瀏覽器解析的主流程
在瀏覽器解析的過程中,DOM節點的解析與CSS節點的解析是同步進行的,之間并不會阻塞,但是一旦涉及到JS的解析,就會導致阻塞,具體規則是這樣的:
1:DOM節點的解析遇到JS時,則會掛起當前DOM的解析過程,直到JS請求和執行完畢后再繼續DOM的解析
2:CSS資源的請求解析遇到JS時,則會阻塞當前的JS,直到CSS資源加載和構建完畢再開始JS的執行(CSS構建styleSheet的時間非常短,可以忽略不計)
*原因如下:腳本在文檔解析階段會請求樣式信息。如果當時還沒有加載和解析樣式,腳本就會獲得錯誤的回復,這樣顯然會產生很多問題。這看上去是一個非典型案例,但事實上非常普遍。Firefox 在樣式表加載和解析的過程中,會禁止所有腳本。而對于 WebKit 而言,僅當腳本嘗試訪問的樣式屬性可能受尚未加載的樣式表影響時,它才會禁止該腳本 *
最后
本文只是讓大家對于瀏覽器的運行和解析機制有基本的了解,如果大家想深入了解瀏覽器內部的運行機制,且后期可能會根據自身理解更新已更新內容,例如DOM如何解析成DOM樹,瀏覽器解析器的運行規則,十分推薦大家去閱讀這篇文章,瀏覽器的工作原理,對于文中有錯誤的點也歡迎大家積極指出,咱們下周見!
總結
以上是生活随笔為你收集整理的ZLL的每周一更(maybe)--浏览器的运行机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: delphi mysql 删除_Delp
- 下一篇: 机器人建模中移动关节如何建立坐标系_简述