背景
作為前端工程師,我們的程式的大多數場景都是執行在瀏覽器環境中,所以今天也想聊一下瀏覽器中渲染我們頁面的一些自己概念和原理
知識點
程式和執行緒是作業系統裡的知識,瞭解了程式和執行緒的概念,有助於理解瀏覽器的執行機制
程式
程式是作業系統進行資源分配和排程的最小單位,電腦中每一個軟體的執行都是一個程式,每個程式都有獨立的一塊記憶體,各個程式之間相互隔離。如果把cpu比作一個工廠的話,程式就相當於一個個獨立的車間
執行緒
執行緒是程式執行中的一個單一的順序控制流程,說白了就相當於是車間裡的每個工人,每個人都有自己的分內工作,互相協同合作完成一個程式車間的正常執行
程式與執行緒的區別和關係
- cpu中包含許多程式,一個程式包含一個或多個執行緒
- 程式之間相互獨立,同一程式下的多個執行緒之間共享程式的記憶體空間(包括程式碼段、資料集、堆等)及一些程式級的資源(如開啟檔案和訊號),但是有些共享記憶體空間同一時刻只允許一個執行緒執行(比如js引擎執行緒執行時,GUI渲染引擎就會被掛起)
多程式與多執行緒
- 多程式:只同一個時間裡,計算機系統允許同時執行多個程式。比如計算機同時開著聊天工具和音樂軟體,保證你能在同時聽歌的情況下和好友聊天
- 多執行緒:在一個程式中,有多個不同分工的執行緒同時執行,相互合作完成各自的任務(瀏覽器中執行的多個執行緒,共同完成頁面的渲染展示)
瀏覽器的多程式架構
在"更多工具" -> "工作管理員"中可以檢視當前瀏覽器中執行的程式 我們可以看到的但不限於以下幾種:
- Browser主程式:協調、主控作用(瀏覽器的主程式,負責瀏覽器介面的顯示、各個頁面的管理、是所有其他型別程式的祖先、負責它們的建立和銷燬等工作,它有且僅有一個)
- GPU程式:用於硬體加速,3D繪製(當且僅當 GPU 硬體加速開啟的時候才會被建立,主要用於對 3D 圖形加速呼叫的實現)
- Renderer渲染程式:每個tab頁的展示
- 第三方擴充套件外掛程式
下面也主要介紹渲染程式: chrome瀏覽器每個tab頁都是一個程式,使用多個程式來隔離頁面,這樣做的好處就是每個tab頁互不影響,當一個tab崩潰的時候不會影響其他網頁,同時程式之間是不共享資源和地址空間的,安全性也能得到更多的保障
瀏覽器核心
又叫渲染引擎,也就是瀏覽器的渲染程式,負責對網頁語法的解釋(html\css\js)並最終渲染呈現給使用者 常見的瀏覽器核心:
- Blink(chrome核心)
- Webkit(safari核心)
- Gecko(Firefox核心) 每一個tab頁都會開啟一個瀏覽器渲染引擎例項,也就是一個獨立的瀏覽器渲染程式 瀏覽器的渲染程式(瀏覽器核心)又包含多個執行緒
- GUI渲染執行緒
- 負責解析HTML、CSS -> 構建DOM樹、CSSOM、Render樹 -> layout佈局 -> 繪製
- 當js操作DOM等原因導致介面發生Repaint或Reflow時,都會觸發GUI執行緒執行
- GUI渲染執行緒與JS引擎執行緒是互斥的,當JS引擎執行緒執行時,GUI渲染引擎會被掛起儲存到一個佇列裡,當JS引擎執行緒空閒時,再開始執行
- JavaScript引擎執行緒
- 又稱為js核心,常用的是Google的V8引擎、火狐的JaegerMonkey引擎等
- 解析JavaScript指令碼,執行程式
- 一個渲染引擎中只包含一個js引擎執行緒,同時JavaScript語言也是單執行緒模式,因為如果JavaScript是多執行緒的方式來操作這些UI DOM,則可能出現UI操作的衝突,這也就是為什麼Web Worker API支援在主執行緒的基礎上多開一個執行緒處理js邏輯,但不允許操作DOM的原因,並且有諸多限制,感興趣的可以瞭解一下
- js程式碼作為一個個任務,由任務佇列統一排程分配,JS引擎一直等待任務佇列中任務到來,有任務過來時,JS引擎執行緒便開始執行
- 因為JavaScript引擎執行緒會導致GUI渲染執行緒掛起的原因,常常會出現js阻塞頁面渲染的現象,這是我們應該儘量避免的
- 事件觸發執行緒
- 我們經常會用到的點選事件等
- 當js引擎執行緒執行程式碼到點選事件時,瀏覽器會將該事件任務新增到事件觸發執行緒中並開始監聽點選事件,當對應的事件滿足條件被觸發時,該執行緒就把觸發事件後的回撥任務新增到task queue佇列中,排隊等待JS引擎執行緒來執行回撥函式
- 定時觸發器執行緒
- setTimeOut\setTimeInterval
- 當JS引擎執行緒執行到setTimeOut\setTimeInterval 關鍵詞時,會把定時器任務新增到定時觸發器執行緒中,定時觸發器執行緒開始執行倒數,當倒數之間到了後,將回撥任務新增到task queue任務佇列中,等待JS引擎執行緒來執行
- 非同步請求執行緒
- 當傳送非同步ajax請求時,瀏覽器會開啟非同步請求執行緒進行http請求
- 當檢測到請求狀態發生變更後,將回撥函式新增到task queue任務佇列中,等待JS引擎執行緒來執行