為什麼瀏覽器採用多程式模型

Horky發表於2015-08-14

為什麼瀏覽器採用多程式模型

這個問題的答案似乎是非常清楚的,可以概括為:為了安全、穩定、效能,只是要犧牲點記憶體作為代價。對於安全和穩定,利用系統的程式機制就可以完成。但是多程式下的程式間通訊(IPC)很慢,而分為多程式後,一些協作任務就要分開到兩個程式,如何能保持良好的效能,更不說比單程式模型更高的效能了? 所以這裡再次探討瀏覽器選擇多程式架構的原因,以及對應架構中的要點。

多程式 vs. 多執行緒

先了解一下背景。將工作並行處理,是提高效能的手段。這個工作涉及到硬體,作業系統和應用程式。我不性硬體,只知道核是越來越多,執行緒的處理能力也是越來越強。從系統的角度來看,似乎可以響應並行處理的資源越來越充分。所以研究如何在多核的時代提高應用的效能是當前的一大熱點。Intel和IBM都有大量關於並行及併發處理的資料和工具。

無論是多執行緒,還是多程式,其目的都是充分利用系統的核心資源,如CPU, I/O, GPU及記憶體等相關的資源,使得任務儘可能的並行完成,以改善應用的響應效能,提高吞吐量。對單個應用而言,其關鍵是解決併發(Concurrency)的問題 (同時跑多個應用是並行處理的問題)。即找到平衡任務和資料依賴的最佳設計,從系統的角度看主要面臨兩個挑戰:
1. 系統資源的競爭。如記憶體,檔案系統等。
2. 上下文切換。
執行緒和程式都有上下文切換的開銷。但在多核下,程式的上下文開銷開始降低。

而從應用程式設計的角度來看,還有兩點:
1. 降低任務依賴。比如執行操作的先後順序問題。
2. 降低資料依賴。比如某個資料的修改和使用會影響到多個任務。

上面所列的四個問題中,無論是多程式,還是多執行緒都要面對。其中多程式在上下文切換的開銷上有先天優勢。

多程式在安全性和穩定性上優於多執行緒模型,一是現代系統都有程式的安全機制,特別是沙箱機制。另外單個程式有獨立的記憶體空間,不像多執行緒共享虛擬記憶體,所以不會因為一個執行緒的崩潰導致整個應用的崩潰。

多程式需要面對的問題包括:
1. 記憶體佔用大,因為無法像多執行緒模型共享公共的記憶體開銷,比如使用的庫,或者某些全域性的資料快取等。這是硬傷。
2. 程式間通訊的成本大。特別是使用共享記憶體交換資料的成本。
3. 程式啟動的開銷大。

後面兩個是效能問題,與前一個並不相同。而且,隨著記憶體配置不斷高升,再配合一些記憶體優化的手段,比如OilPan, 第一個問題並不算太迫切。而後面兩個問題,相對於頁面渲染的開銷,只要限定在一定範圍,也不會有太大的影響。所以限定的規則就很重要。

瀏覽器對多程式的需求

決定瀏覽器採用多程式架構還是多執行緒架構,並不是取決於效能。因為從上面的分析也能看出來,多程式模型和多執行緒模式相比,只要將IPC和啟動的開銷降低,其效能的高低仍然取決於各個程式中的執行緒設計。

結合Google和Mozilla對各自採用多程式架構的說明,可以瞭解到促使瀏覽器採用多程式架構的是越來越複雜的頁面。以下以Chromium的研究論文為主,Mozilla關於Multiprocess Firefox的說明也主要說明之前的效能優化也是可以使用多程式的方式實現的,所以不再詳細說明。

現在的頁面越來越複雜,H5, Webapp,或者Hybrid App等等,它們執行的任務越來越重,不再像以前都是文件型別的頁面,現在的頁面更像是一個應用。它們對系統資源的需求變大,同時不穩定的機率也增大。如果同時開啟多個頁面,就會引入更長的操作延遲,嚴重影響使用者體驗。

頁面瀏覽中核心的功能是頁面的渲染(從DOM Tree到Render Tree),JS的執行, 它是一個需要集中運算的功能,相對獨立於系統資源的使用。而系統資源的使用又可以集中起來共享使用,也有利於將不安全的頁面與系統資源隔離開來(沙箱機制的需求)。於是就形成了現在程式架構:
chrome_architecture
上面多個Renderer Engines和Plugin-in程式和一個Browser程式構成了Chromium的程式模型。

所以再結合這點思考,為什麼Chromium強調對資料庫的操作都要拋到Browser程式來完成?

關於效能

我們先看一下Google論證多程式性的資料。他們當時(2009)特別選了一臺雙核的電腦來進行測試,所有的載入都是從本地檔案載入,以避免網路的影響。最終測試的效能資料對比如下:
process_02_performance
Startup是啟動並且開新頁面的時間,New Tab是在新頁籤開啟頁面的時間,Navigation則是頁面上開啟新頁面的時間。Monolithic是單程式,另一個不用說了。
為什麼啟動並開新頁面的時間也變快了?原因當然是程式啟動引入的開銷其實是很小的,開頁面帶來的收益要遠大於它。

再看一下載入頁面到可操作及載入完成所需要的時間:
process_03_loading
對於單程式模型,基本要等載入完了才能操作。而多程式模型下,頁面渲染與使用者操作能夠分別響應。當然在單程式模型,利用中斷的方式也能達到相似的效果。

這些是Chromium在對IPC和程式中系統資源操作進行嚴格限制所達到的效果。如果破壞了這些限制,效能就不見得這樣理想了。

單程式的Android WebView效能差嗎

看一下Google工程師的回覆吧:

By Bo.Liu
Any difference between multiprocess and multithread 
should not be significant enough to be noticeable to
 users.

Webview's rendering and threading architecture is
 different from chrome, and what you are probably wanted
 to know is whether this hurts webview's performance.
The answer is depends. Webview merges some chrome
 threads into a single one. The down side is webview is
 more suspetible to thread contention and may not take 
 advantage of large number of cpu cores. The up side is 
 that there is generally less thread hopping, so webview 
 has an easier time performing consistently on less 
 powerful hardware.

大意為有得有失,關鍵是“視情況而定”。缺點是執行緒競爭相對嚴重了,好處是執行緒切換少了,效能差的手機也能跑得不錯。 引申的意思就是如果是好手機,效能還是有差距的。 還有一個他沒說的,單程式下的安全、穩定性又回到過去的狀態了,長時間使用後的記憶體碎片現象也一起回來了。

參考:

Isolating Web Programs in Modern Browser Architectures
Multiprocess Firefox
Thread Scheduling in Android)

相關文章