瀏覽器進程線程1

本篇文章參考自撒網要見魚大佬的 僅供本身學習提高。html

https://segmentfault.com/a/11...前端

區分線程和進程

**- 什麼是進程**

狹義定義:進程是正在運行的程序的實例(an instance of a computer program that is being executed)。

廣義定義:進程是一個具備必定獨立功能的程序關於某個數據集合的一次運行活動。它是操做系統動態執行的基本單元,在傳統的操做系統中,進程既是基本的分配單元,也是基本的執行單元。

**- 什麼是線程**

線程(英語:thread)是操做系統可以進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運做單位。一條線程指的是進程中一個單一順序的控制流,一個進程中能夠併發多個線程,每條線程並行執行不一樣的任務。

在當代面向線程設計的計算機結構中,進程是線程的容器。segmentfault

先看個形象的比喻:瀏覽器

- 進程是一個工廠,工廠有它的獨立資源

- 工廠之間相互獨立

- 線程是工廠中的工人,多個工人協做完成任務

- 工廠內有一個或多個工人

- 工人之間共享空間

再完善完善概念:網絡

- 工廠的資源 -> 系統分配的內存(獨立的一塊內存)

- 工廠之間的相互獨立 -> 進程之間相互獨立

- 多個工人協做完成任務 -> 多個線程在進程中協做完成任務

- 工廠內有一個或多個工人 -> 一個進程由一個或多個線程組成

- 工人之間共享空間 -> 同一進程下的各個線程之間共享程序的內存空間(包括代碼段、數據集、堆等)

而後再鞏固下:多線程

能夠打開任務管理器,能夠看到有一個後臺進程列表。這裏就是查看進程的地方,並且能夠看到每一個進程的內存資源信息以及cpu佔有率。併發

圖片描述

瀏覽器是多線程的

理解了進程與線程了區別後,接下來對瀏覽器進行必定程度上的認識:(先看下簡化理解)異步

  • 瀏覽器是多進程的
  • 瀏覽器之因此可以運行,是由於系統給它的進程分配了資源(cpu、內存)
  • 簡單點理解,每打開一個Tab頁,就至關於建立了一個獨立的瀏覽器進程。

圖片描述

圖中打開了Chrome瀏覽器的多個標籤頁,而後能夠在Chrome的任務管理器中看到有多個進程(分別是每個Tab頁面有一個獨立的進程,以及一個主進程)。函數

注意:在這裏瀏覽器應該也有本身的優化機制,有時候打開多個tab頁後,能夠在Chrome任務管理器中看到,有些進程被合併了oop

瀏覽器都包含哪些進程?

主要包含哪些進程:(爲了簡化理解,僅列舉主要進程)

  • Browser進程:瀏覽器的主進程(負責協調、主控),只有一個。做用有

    • 負責瀏覽器界面顯示,與用戶交互。如前進,後退等
    • 負責各個頁面的管理,建立和銷燬其餘進程
    • 將Renderer進程獲得的內存中的Bitmap,繪製到用戶界面上
    • 網絡資源的管理,下載等
  • 第三方插件進程:每種類型的插件對應一個進程,僅當使用該插件時才建立
  • GPU進程:最多一個,用於3D繪製等
  • 瀏覽器渲染進程(瀏覽器內核)(Renderer進程,內部是多線程的):默認每一個Tab頁面一個進程,互不影響。主要做用爲

    • 頁面渲染,腳本執行,事件處理等

強化記憶:在瀏覽器中打開一個網頁至關於新起了一個進程(進程內有本身的多線程)

瀏覽器多進程的優點

相比於單進程瀏覽器,多進程有以下優勢:

  • 避免單個page crash影響整個瀏覽器
  • 避免第三方插件crash影響整個瀏覽器
  • 多進程充分利用多核優點
  • 方便使用沙盒模型隔離插件等進程,提升瀏覽器穩定性

    簡單點理解:若是瀏覽器是單進程,那麼某個Tab頁崩潰了,就影響了整個瀏覽器,體驗有多差;同理若是是單進程,插件崩潰了也會影響整個瀏覽器;

重點是瀏覽器內核(渲染進程)

對於普通的前端操做來講,頁面的渲染,JS的執行,事件的循環,都在這個進程內進行。瀏覽器的渲染進程是多線程的。

渲染進程包含哪些主要的線程?

1.GUI渲染線程【圖形用戶界面(Graphical User Interface,簡稱 GUI,又稱圖形用戶接口)】

  • 負責渲染瀏覽器界面,解析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引擎的處理(事件循環 Event Loop)
  • 注意,因爲JS的單線程關係,因此這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閒時纔會去執行)

4.定時觸發器線程

  • 傳說中的setInterval與setTimeout所在線程
  • 瀏覽器定時計數器並非由JavaScript引擎計數的,(由於JavaScript引擎是單線程的, 若是處於阻塞線程狀態就會影響記計時的準確)
  • 所以經過單獨線程來計時並觸發定時【計時完畢後,添加到事件隊列中,等待JS引擎空閒後執行,這也是「JavaScript定時器不許確」的緣由(可用requestAnimationFrame)】
  • 注意,W3C在HTML標準中規定,規定要求setTimeout中低於4ms的時間間隔算爲4ms。

5.異步http請求線程

  • 在XMLHttpRequest在鏈接後是經過瀏覽器新開一個線程請求
  • 將檢測到狀態變動時,若是設置有回調函數,異步線程就產生狀態變動事件,將這個回調再放入事件隊列中。再由JavaScript引擎執行。

圖片描述

爲何JS引擎是單線程的?爲何須要異步? 單線程又是如何實現異步的呢? 查看【連接描述

Browser進程和瀏覽器內核(Renderer進程)的通訊過程

若是本身打開任務管理器,而後打開一個瀏覽器,就能夠看到:任務管理器中出現了兩個進程(一個是主控進程,一個則是打開Tab頁的渲染進程),
而後在這前提下,看下整個的過程:(簡化了不少)

  • Browser進程收到用戶請求,首先須要獲取頁面內容(譬如經過網絡下載資源),隨後將該任務經過RendererHost接口傳遞給Render進程
  • Renderer進程的Renderer接口收到消息,簡單解釋後,交給渲染線程,而後開始渲染

    • 渲染線程接收請求,加載網頁並渲染網頁,這其中可能須要Browser進程獲取資源和須要GPU進程來幫助渲染
    • 固然可能會有JS線程操做DOM(這樣可能會形成迴流並重繪)
    • 最後Render進程將結果傳遞給Browser進程
  • Browser進程接收到結果並將結果繪製出來

這裏繪一張簡單的圖:(很簡化)

圖片描述

梳理瀏覽器內核中線程之間的關係

GUI渲染線程與JS引擎線程互斥

因爲JavaScript是可操縱DOM的,若是在修改這些元素屬性同時渲染界面(即JS線程和UI線程同時運行),那麼渲染線程先後得到的元素數據就可能不一致了。

所以爲了防止渲染出現不可預期的結果,瀏覽器設置GUI渲染線程與JS引擎爲互斥的關係,當JS引擎執行時GUI線程會被掛起,
GUI更新則會被保存在一個隊列中等到JS引擎線程空閒時當即被執行。

從上述的互斥關係,能夠推導出,JS若是執行時間過長就會阻塞頁面。

譬如,假設JS引擎正在進行巨量的計算,此時就算GUI有更新,也會被保存到隊列中,等待JS引擎空閒後執行。
而後,因爲巨量計算,因此JS引擎極可能好久好久後才能空閒,天然會感受到巨卡無比。

因此,要儘可能避免JS執行時間過長,這樣就會形成頁面的渲染不連貫,致使頁面渲染加載阻塞的感受。

相關文章
相關標籤/搜索