最後下面的渲染進程可能有多個(每一個tab頁面瀏覽器都會啓動一個渲染進程)css
瀏覽器的主進程(負責協調、主控),只有一個。html
負責瀏覽器界面顯示,與用戶交互。如前進,後退等web
負責各個頁面的管理,建立和銷燬其餘進程segmentfault
將Renderer進程獲得的內存中的Bitmap,繪製到用戶界面上瀏覽器
網絡資源的管理,下載等服務器
每種類型的插件對應一個進程,僅當使用該插件時才建立網絡
最多一個,用於3D繪製等多線程
默認每一個Tab頁面都會產生一個渲染進程,互不影響。主要做用爲
頁面渲染,腳本執行,事件處理等dom
打開Chrome Shift+Esc;咱們能夠看到進程狀況,Chrome圖標就是Browser主進程異步
避免單個page crash影響整個瀏覽器
避免第三方插件crash影響整個瀏覽器
多進程充分利用多核優點
方便使用沙盒模型隔離插件等進程,提升瀏覽器穩定性
簡單點理解:若是瀏覽器是單進程,那麼某個Tab頁崩潰了,就影響了整個瀏覽器,體驗有多差;同理若是是單進程,插件崩潰了也會影響整個瀏覽器;並且多進程還有其它的諸多優點,固然內存等資源消耗也會更大
負責渲染瀏覽器界面,解析HTML,CSS,構建DOM樹和RenderObject樹,佈局和繪製等。
當界面須要重繪(Repaint)或因爲某種操做引起迴流(reflow)時,該線程就會執行
注意,GUI渲染線程與JS引擎線程是互斥的,當JS引擎執行時GUI線程會被掛起(至關於被凍結了),GUI更新會被保存在一個隊列中等到JS引擎空閒時當即被執行。
爲何互斥:因爲 JS 是能夠操做 DOM 的,若是同時修改元素屬性並同時渲染界面(即 JS線程和UI線程同時運行), 那麼渲染線程先後得到的元素就可能不一致了(簡單說就是js修改dom後沒有從新渲染成功)
也稱爲JS內核,負責處理Javascript腳本程序。(例如V8引擎)
JS引擎線程負責解析Javascript腳本,運行代碼。
JS引擎一直等待着任務隊列中任務的到來,而後加以處理,一個Tab頁(renderer進程)中不管何時都只有一個JS線程在運行JS程序
一樣注意,GUI渲染線程與JS引擎線程是互斥的,因此若是JS執行的時間過長,這樣就會形成頁面的渲染不連貫,致使頁面渲染加載阻塞。
歸屬於瀏覽器而不是JS引擎,用來控制事件循環(能夠理解,JS引擎本身都忙不過來,須要瀏覽器另開線程協助)
當JS引擎執行代碼塊如setTimeOut時(也可來自瀏覽器內核的其餘線程,如鼠標點擊、AJAX異步請求等),會將對應任務添加到事件線程中
當對應的事件符合觸發條件被觸發時,該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理
注意,因爲JS的單線程關係,因此這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閒時纔會去執行)
傳說中的setInterval與setTimeout所在線程
瀏覽器定時計數器並非由JavaScript引擎計數的,(由於JavaScript引擎是單線程的, 若是處於阻塞線程狀態就會影響記計時的準確)
所以經過單獨線程來計時並觸發定時(計時完畢後,添加到事件隊列中,等待JS引擎空閒後執行)
注意,W3C在HTML標準中規定,規定要求setTimeout中低於4ms的時間間隔算爲4ms。
在XMLHttpRequest在鏈接後是經過瀏覽器新開一個線程請求
將檢測到狀態變動時,若是設置有回調函數,異步線程就產生狀態變動事件,將這個回調再放入事件隊列中。再由JavaScript引擎執行。
因爲JavaScript是可操縱DOM的,若是在修改這些元素屬性同時渲染界面(即JS線程和UI線程同時運行),那麼渲染線程先後得到的元素數據就可能不一致了。
所以爲了防止渲染出現不可預期的結果,瀏覽器設置GUI渲染線程與JS引擎爲互斥的關係,當JS引擎執行時GUI線程會被掛起,
GUI更新則會被保存在一個隊列中等到JS引擎線程空閒時當即被執行。
從上述的互斥關係,能夠推導出,JS若是執行時間過長就會阻塞頁面。
譬如,假設JS引擎正在進行巨量的計算,此時就算GUI有更新,也會被保存到隊列中,等待JS引擎空閒後執行。
而後,因爲巨量計算,因此JS引擎極可能好久好久後才能空閒,天然會感受到巨卡無比。
因此,要儘可能避免JS執行時間過長,這樣就會形成頁面的渲染不連貫,致使頁面渲染加載阻塞的感受。
JavaScript引擎是單線程運行的,JavaScript中耗時的I/O操做都被處理爲異步操做,它們包括鍵盤、鼠標I/O輸入輸出事件、窗口大小的resize事件、定時器(setTimeout、setInterval)事件、Ajax請求網絡I/O回調等。當這些異步任務發生的時候,它們將會被放入瀏覽器的事件任務隊列中去,等到JavaScript運行時執行線程空閒時候纔會按照隊列先進先出的原則被一一執行,但終究仍是單線程。
建立Worker時,JS引擎向瀏覽器申請開一個子線程(子線程是瀏覽器開的,徹底受主線程控制,並且不能操做DOM)
JS引擎線程與worker線程間經過特定的方式通訊(postMessage API,須要經過序列化對象來與線程交互特定的數據)
//主線程 main.js var worker = new Worker("worker.js"); worker.onmessage = function(event){ // 主線程收到子線程的消息 }; // 主線程向子線程發送消息 worker.postMessage({ type: "start", value: 12345 }); //web worker.js onmessage = function(event){ // 收到 }; postMessage({ type: "debug", message: "Starting processing..." });
瀏覽器使用流式佈局模型 (Flow Based Layout)。
有了RenderTree,咱們就知道了全部節點的樣式,而後計算他們在頁面上的大小和位置,最後把節點繪製到頁面上。
當Render Tree中部分或所有元素的尺寸、結構、或某些屬性發生改變時,瀏覽器從新渲染部分或所有文檔的過程稱爲迴流。
當頁面中元素樣式的改變並不影響它在文檔流中的位置時(例如:color、background-color、visibility等),瀏覽器會將新樣式賦予給元素並從新繪製它,這個過程稱爲重繪。