Chrome 多進程架構

問題

    構建一個永遠不會崩潰或者掛起的排版引擎基本是不可能的,咱們一樣也不要期望哪天可以構建出一個絕對安全的排版引擎。php

    咱們現階段的瀏覽器運行在一個單用戶,多合做,多任務的操做系統中。就像一個笨拙的應用程序可讓整個系統崩潰同樣。一個糟糕的網頁一樣可讓一個現代的瀏覽器崩潰。其緣由多是一個插件出現bug,最終的結果是整個瀏覽器以及其餘正在運行的標籤被銷燬。html

    現代操做系統已經很是健壯了,它讓應用程序在各自的進程中運行和不會影響到其餘程序。一個進程崩潰不會損害到其餘進程以及操做系統。同時系統會嚴格的限制一個用戶訪問另一個用戶空間的數據。web

架構總攬

    咱們爲瀏覽器的每一個標籤(Tab)開闢一個獨立的進程,這樣咱們防止整個應用程序由於排版引擎的bug而崩潰。一樣咱們會嚴格限制進程訪問操做系統及其內存空間。windows

    咱們將運行UI和管理標籤的插件線程稱之爲"瀏覽器進程"或者說是"瀏覽器",一樣,咱們將每一個標籤相關的進程稱之爲"排版進程"或者說是"排版"。咱們使用開源的WebKit做爲HTML的解析和排版引擎。瀏覽器

管理排版(Render)進程

每一個排版進程都有一個全局的RenderProcess 的對象用以管理和父瀏覽器進程之間的通信而且保持全局狀態。瀏覽器每個排版進程保持一個對應的RenderProcessHost對象用以管理瀏覽器狀態並負責與其餘排版進程進行通信。瀏覽器進程和排版進程經過Chromium的IPC系統進行通信。安全

管理視圖(Views)

每一個排版進程包含一個或多個RenderView 對象。RenderProcess對象負責管理RenderView 對象以及標籤(Tabs)的內容。RenderProcessHost裏面包含有RenderViewHost。網絡

同時每一個RenderViewHost對應着排版進程的一個視圖。在一個排版進程裏面的視圖都有一個不一樣的視圖ID。這些視圖ID有可能和其餘排版進程裏面的視圖ID重名。所以咱們肯定一個位於的視圖須要同時藉助RenderProcessHost和視圖ID。瀏覽器經過RenderViewHost 對象與指定標籤的內容進行通信。RenderViewHost 經過RenderProcessHost 傳遞消息給RenderView上的RenderProcess 對象。架構

組件和接口

在排版進程內:ide

  • RenderProcess  經過IPC與瀏覽器內對應的 RenderProcess 進行通信。每個排版進程包含一個惟一的 RenderProcess  對象。
  • RenderView 對象負責聯繫瀏覽器進程裏面的RenderView Host對象(經過RenderProcess)和WebKit排版引擎。RenderView 負責顯示每一個標籤下的網頁以及彈出窗口。

   

在瀏覽器進程內:性能

  • Browser 對象負責顯示最上層的瀏覽器窗口。
  • RenderProcessHost 對象顯示單個瀏覽器的側邊  ↔ 排版進程的IPC鏈接(ps:不太理解這句話,付原文以下: The RenderProcessHost  object represents the browser side of a single browser ↔ renderer IPC connection)。每一個排版進程僅有一個 RenderProcessHost 對象。
  • RenderViewHost 對象封裝與遠程 RenderView 之間的通信。同時負責 RenderWidget對象的輸入和顯示。

    更多細節能夠參考 How Chromium displays web pages 

排版進程的共享

    一般狀況下。每頁新窗口或者是新標籤都將在新進程裏面打開。瀏覽器進程負責建立新進程並引導它建立一個RenderView

    有時候有必要讓標籤或者是窗口共享排版線程。一個網頁應用開啓了一個新的窗口並採用同步實現進行通信。例如:Javasript裏面的window.open。在這種狀況下,當咱們建立一個新的窗口或者一個新的標籤。咱們須要重用當前進程打開的窗口。咱們還有一種策略:當建立進程的數量太多的時候,咱們會把新建立的標籤附加到已有的進程上。或者當用戶已經有一個進程打開了所需的地址。這個策略咱們已經在in Process Models. 裏面描述過。

崩潰檢測或異常排版

       每一個瀏覽器進程的IPC鏈接會監視進程的句柄(handle),若是句柄指示異常(are signaled),排版引擎已經崩潰並並通知到標籤。而後咱們會顯示一個"sab tab"頁面通知用戶排版引擎已經崩潰。這個頁面能夠經過按刷新鍵從新加載或者輸入一個新的地址進行瀏覽。當這種狀況發生時,咱們通知用戶原來的進程已經不存在了咱們須要創新一個新的進程。

排版引擎的沙盒模型

        當咱們將WebKit至於一個獨立的進程內,就給了咱們機會去限制它訪問系統資源。例如,咱們能夠確保排版引擎的對網絡的訪問都是經過它的父進程完成的。一樣,咱們能夠經過操做系統內置的權限限制排版引擎對文件系統的訪問。

         除了可以限制排版引擎對文件系統和網絡的訪問外,咱們還能夠增長對其對用戶的顯示和相關對象的限制。咱們能夠在一個用戶不可見的windows 桌面上運行一個排版進程。

         這樣咱們能夠防止排版引擎打開新的窗口或者被劫持按鍵。

返還內存

     給定的排版引擎運做在獨立的進程內,它會將隱藏的標籤當作低優先級處理。一般狀況下,被最小化的窗口的進程會講他們的內存自動返還到"能夠內存"池內,在低內存狀況下。窗口會將這部份內存交換到高優先級內存。這樣能夠保證用戶可視的程序獲得更多相應。咱們能夠講這個策略用於隱藏的標籤。當一個排版進程沒有最上層的標籤,咱們能夠減少這個進程的工做設置大小,這樣會提示系統若是有須要能夠講這個進程的內存優先交換出去。由於咱們發現減小工做設置大小會下降兩個標籤間的切換速度,咱們採起逐步釋放的策略。這意味着若是用戶在經常使用標籤間切換的時候,那些不常被使用的標籤其內存會優先被置換出去。

用戶若是有足夠多的內存運行他們因此的程序的時候他們是不會體會到這個差異的。系統僅僅會回收須要的內存,若是你有足夠的內存是不會有性能損失的。

    這會幫助咱們在低內存環境下獲取更多優化的內存足跡。那些不常使用且被置於後天的標籤其內存能夠徹底交換給前置的標籤。於此造成對比的是,一個單進程瀏覽器,它全部標籤的數據僅僅會隨意的散落在內存中,而其不可能將使用過和未使用的內存區分開,既浪費了內存空間有損害了系統性能。

插件

Firefox形式的NPAPI 插件運行在他們本身的進程內,同其餘的排版進程保持分離。這些在Plugin Architecture.有進一步的描述

 

資源

Multi-threaded user interface in Windows on MSDN.

 



本文翻譯自http://dev.chromium.org/developers/design-documents/multi-process-architecture

轉:http://www.cppblog.com/vlient/archive/2008/10/12/63782.html

相關文章
相關標籤/搜索