前言
本文是筆者對(duì)Mario Kosaka寫的inside look at modern web browser系列文章的翻譯落午。這里的翻譯不是指直譯贬墩,而是結(jié)合個(gè)人的理解將作者想表達(dá)的意思表達(dá)出來存谎,而且會(huì)盡量補(bǔ)充一些相關(guān)的內(nèi)容來幫助大家更好地理解开泽。
CPU烦周,GPU做粤,內(nèi)存和多進(jìn)程架構(gòu)
在這個(gè)4集系列教程里面羊异,我將會(huì)從Chrome瀏覽器的高層次架構(gòu)(high-level architecture)開始說起事秀,一直深入講到頁(yè)面渲染流水線(rendering pipeline)的具體細(xì)節(jié)。如果你想知道瀏覽器是怎么把你編寫的代碼轉(zhuǎn)變成一個(gè)可用的網(wǎng)站野舶,或者你不知道為什么一些特定的代碼寫法可以提高網(wǎng)站的性能的易迹,那你就來對(duì)地方了,這篇文章就是為你準(zhǔn)備的平道。
作為本系列文章的第一篇睹欲,我們會(huì)先了解一些關(guān)鍵的計(jì)算機(jī)術(shù)語(yǔ)以及Chrome瀏覽器的多進(jìn)程架構(gòu)。
計(jì)算機(jī)的核心 - CPU和GPU
要想理解瀏覽器的運(yùn)行環(huán)境一屋,我們先要搞明白一些計(jì)算機(jī)組件以及它們的作用窘疮。
CPU
首先我們要說的是計(jì)算機(jī)的大腦 - CPU(Central Processing Unit)。CPU是計(jì)算機(jī)里面的一塊芯片冀墨,上面有一個(gè)或者多個(gè)核心(core)闸衫。我們可以把CPU的一個(gè)核心(core)比喻成一個(gè)辦公室工人,他功能強(qiáng)大诽嘉,上知天文下知地理蔚出,琴棋書畫無所不能,它可以串行地一件接著一件處理交給它的任務(wù)虫腋。很久之前的時(shí)候大多數(shù)CPU只有一個(gè)核心骄酗,不過在現(xiàn)在的硬件設(shè)備上CPU通常會(huì)有多個(gè)核心,因?yàn)槎嗪诵腃PU可以大大提高手機(jī)和電腦的運(yùn)算能力悦冀。
<p align="center">四個(gè)CPU核心愉快地在各自工位上一個(gè)接著一個(gè)地處理交給它們的任務(wù)</p>
GPU
圖形處理器 - 或者說GPU(Graphics Processing Unit)是計(jì)算機(jī)的另外一個(gè)重要組成部分趋翻。和功能強(qiáng)大的CPU核心不一樣的是,單個(gè)GPU核心只能處理一些簡(jiǎn)單的任務(wù)雏门,不過它勝在數(shù)量多嘿歌,單片GPU上會(huì)有很多很多的核心可以同時(shí)工作,也就是說它的并行計(jì)算能力是非常強(qiáng)的茁影。圖形處理器(GPU)顧名思義一開始就是專門用來處理圖形的宙帝,所以在說到圖形使用GPU(using)或者GPU支持(backed)時(shí),人們就會(huì)聯(lián)想到圖形快速渲染或者流暢的用戶體驗(yàn)相關(guān)的概念募闲。最近幾年來步脓,隨著GPU加速概念的流行,在GPU上單獨(dú)進(jìn)行的計(jì)算也變得越來越多了。
<p align="center">每個(gè)GPU核心手里只有一個(gè)扳手靴患,這就說明它的能力是非常有限的仍侥,可是它們?nèi)硕喟。?lt;/p>
當(dāng)你在手機(jī)或者電腦上打開某個(gè)應(yīng)用程序的時(shí)候鸳君,背后其實(shí)是CPU和GPU支撐著這個(gè)應(yīng)用程序的運(yùn)行农渊。通常來說,你的應(yīng)用要通過操作系統(tǒng)提供的一些機(jī)制才能跑在CPU和GPU上面或颊。
<p align="center">計(jì)算機(jī)的三層架構(gòu)砸紊,最下層是硬件機(jī)器,操作系統(tǒng)夾在中間囱挑,最上層是運(yùn)行的應(yīng)用</p>
在進(jìn)程和線程上執(zhí)行程序
在深入到瀏覽器的架構(gòu)之前我們還得了解一下進(jìn)程(process)和線程(thread)的相關(guān)概念醉顽。進(jìn)程可以看成正在被執(zhí)行的應(yīng)用程序(executing program)。而線程是跑在進(jìn)程里面的平挑,一個(gè)進(jìn)程里面可能有一個(gè)或者多個(gè)線程游添,這些線程可以執(zhí)行任何一部分應(yīng)用程序的代碼。
<p align="center">進(jìn)程就像一個(gè)大魚缸通熄,而線程就是浴缸里面暢游的魚兒</p>
當(dāng)你啟動(dòng)一個(gè)應(yīng)用程序的時(shí)候唆涝,操作系統(tǒng)會(huì)為這個(gè)程序創(chuàng)建一個(gè)進(jìn)程同時(shí)還為這個(gè)進(jìn)程分配一片私有的內(nèi)存空間,這片空間會(huì)被用來存儲(chǔ)所有程序相關(guān)的數(shù)據(jù)和狀態(tài)棠隐。當(dāng)你關(guān)閉這個(gè)程序的時(shí)候石抡,這個(gè)程序?qū)?yīng)的進(jìn)程也會(huì)隨之消失,進(jìn)程對(duì)應(yīng)的內(nèi)存空間也會(huì)被操作系統(tǒng)釋放掉助泽。
<p align="center">進(jìn)程使用系統(tǒng)分配的內(nèi)存空間去存儲(chǔ)應(yīng)用的數(shù)據(jù)</p>
有時(shí)候?yàn)榱藵M足功能的需要,創(chuàng)建的進(jìn)程會(huì)叫系統(tǒng)創(chuàng)建另外一些進(jìn)程去處理其它任務(wù)嚎京,不過新建的進(jìn)程會(huì)擁有全新的獨(dú)立的內(nèi)存空間而不是和原來的進(jìn)程共用內(nèi)存空間嗡贺。如果這些進(jìn)程需要通信,它們要通過IPC機(jī)制(Inter Process Communication)來進(jìn)行鞍帝。很多應(yīng)用程序都會(huì)采取這種多進(jìn)程的方式來工作诫睬,因?yàn)檫M(jìn)程和進(jìn)程之間是互相獨(dú)立的它們互不影響,換句話來說帕涌,如果其中一個(gè)工作進(jìn)程(worker process)掛掉了其他進(jìn)程不會(huì)受到影響摄凡,而且掛掉的進(jìn)程還可以重啟。
<p align="center">不同的進(jìn)程通過IPC來通信</p>
瀏覽器架構(gòu)
那么瀏覽器是怎么使用進(jìn)程和線程來工作的呢蚓曼?其實(shí)大概可以分為兩種架構(gòu)亲澡,一種是單進(jìn)程架構(gòu),也就是只啟動(dòng)一個(gè)進(jìn)程纫版,這個(gè)進(jìn)程里面有多個(gè)線程工作床绪。第二種是多進(jìn)程架構(gòu),瀏覽器會(huì)啟動(dòng)多個(gè)進(jìn)程,每個(gè)進(jìn)程里面有多個(gè)線程癞己,不同進(jìn)程通過IPC進(jìn)行通信膀斋。
<p align="center">單進(jìn)程和多進(jìn)程瀏覽器的架構(gòu)圖</p>
上面的圖表架構(gòu)其實(shí)包含了瀏覽器架構(gòu)的具體實(shí)現(xiàn)了,在現(xiàn)實(shí)中其實(shí)并沒有一個(gè)大家都遵循的瀏覽器實(shí)現(xiàn)標(biāo)準(zhǔn)痹雅,所以不同瀏覽器的實(shí)現(xiàn)方式可能會(huì)完全不一樣仰担。
為了更好地在本系列文章中展開論述,我們主要討論最新的Chrome瀏覽器架構(gòu)绩社,它采用的是多進(jìn)程架構(gòu)惰匙,以下是架構(gòu)圖:
<p align="center">Chrome的多進(jìn)程架構(gòu)圖,多個(gè)渲染進(jìn)程的卡片(render process)是用來表明Chrome會(huì)為每一個(gè)tab創(chuàng)建一個(gè)渲染進(jìn)程铃将。</p>
Chrome瀏覽器會(huì)有一個(gè)瀏覽器進(jìn)程(browser process)项鬼,這個(gè)進(jìn)程會(huì)和其他進(jìn)程一起協(xié)作來實(shí)現(xiàn)瀏覽器的功能。對(duì)于渲染進(jìn)程(renderer process)劲阎,Chrome會(huì)盡可能為每一個(gè)tab甚至是頁(yè)面里面的每一個(gè)iframe都分配一個(gè)單獨(dú)的進(jìn)程绘盟。
各個(gè)進(jìn)程如何分工合作呢?
以下是各個(gè)進(jìn)程具體負(fù)責(zé)的工作內(nèi)容:
進(jìn)程 | 負(fù)責(zé)的工作 |
---|---|
Browser | 負(fù)責(zé)瀏覽器的“Chrome”部分悯仙, 包括導(dǎo)航欄龄毡,書簽, 前進(jìn)和后退按鈕锡垄。同時(shí)這個(gè)進(jìn)程還會(huì)控制那些我們看不見的部分沦零,包括網(wǎng)絡(luò)請(qǐng)求的發(fā)送以及文件的讀寫。 |
Renderer | 負(fù)責(zé)tab內(nèi)和網(wǎng)頁(yè)展示相關(guān)的所有工作货岭。 |
Plugin | 控制網(wǎng)頁(yè)使用的所有插件路操,例如flash插件。 |
GPU | 負(fù)責(zé)獨(dú)立于其它進(jìn)程的GPU任務(wù)千贯。它之所以被獨(dú)立為一個(gè)進(jìn)程是因?yàn)樗幚韥碜杂诓煌瑃ab的渲染請(qǐng)求并把它在同一個(gè)界面上畫出來屯仗。 |
<p align="center">不同的進(jìn)程負(fù)責(zé)瀏覽器不同部分的界面內(nèi)容</p>
除了上面列出來的進(jìn)程,Chrome還有很多其他進(jìn)程在工作搔谴,例如擴(kuò)展進(jìn)程(Extension Process)和工具進(jìn)程(utility process)魁袜。如果你想看一下你的Chrome瀏覽器現(xiàn)在有多少個(gè)進(jìn)程在跑可以點(diǎn)擊瀏覽器右上角的更多按鈕,選擇更多工具和任務(wù)管理器:
在彈出的窗口里面你會(huì)看到正在工作的進(jìn)程列表敦第,以及每個(gè)進(jìn)程使用的CPU和內(nèi)存狀況峰弹。
Chrome多進(jìn)程架構(gòu)的好處
那么為什么Chrome會(huì)采取多進(jìn)程架構(gòu)工作呢?
其中一個(gè)好處是多進(jìn)程可以使瀏覽器具有很好的容錯(cuò)性芜果。對(duì)于大多數(shù)簡(jiǎn)單的情景來說鞠呈,Chrome會(huì)為每個(gè)tab單獨(dú)分配一個(gè)屬于它們的渲染進(jìn)程(render process)。舉個(gè)例子师幕,假如你有三個(gè)tab粟按,你就會(huì)有三個(gè)獨(dú)立的渲染進(jìn)程诬滩。當(dāng)其中一個(gè)tab的崩潰時(shí),你可以隨時(shí)關(guān)閉這個(gè)tab并且其他tab不受到影響灭将√勰瘢可是如果所有的tab都跑在同一個(gè)進(jìn)程的話,它們就會(huì)有連帶關(guān)系庙曙,一個(gè)掛全部掛空镜。
<p align="center">不同的tab會(huì)有不同的渲染進(jìn)程來負(fù)責(zé)</p>
Chrome采用多進(jìn)程架構(gòu)的另外一個(gè)好處就是可以提供安全性和沙盒性(sanboxing)。因?yàn)椴僮飨到y(tǒng)可以提供方法讓你限制每個(gè)進(jìn)程擁有的能力捌朴,所以瀏覽器可以讓某些進(jìn)程不具備某些特定的功能吴攒。例如,由于tab渲染進(jìn)程可能會(huì)處理來自用戶的隨機(jī)輸入砂蔽,所以Chrome限制了它們對(duì)系統(tǒng)文件隨機(jī)讀寫的能力洼怔。
不過多進(jìn)程架構(gòu)也有它不好的地方,那就是進(jìn)程的內(nèi)存消耗左驾。由于每個(gè)進(jìn)程都有各自獨(dú)立的內(nèi)存空間镣隶,所以它們不能像存在于同一個(gè)進(jìn)程的線程那樣共用內(nèi)存空間,這就造成了一些基礎(chǔ)的架構(gòu)(例如V8 JavaScript引擎)會(huì)在不同進(jìn)程的內(nèi)存空間同時(shí)存在的問題诡右,這些重復(fù)的內(nèi)容會(huì)消耗更多的內(nèi)存安岂。所以為了節(jié)省內(nèi)存,Chrome會(huì)限制被啟動(dòng)的進(jìn)程數(shù)目帆吻,當(dāng)進(jìn)程數(shù)達(dá)到一定的界限后域那,Chrome會(huì)將訪問同一個(gè)網(wǎng)站的tab都放在一個(gè)進(jìn)程里面跑。
節(jié)省更多的內(nèi)存 - Chrome的服務(wù)化
同樣的優(yōu)化方法也可以被使用在瀏覽器進(jìn)程(browser process)上面猜煮。Chrome瀏覽器的架構(gòu)正在發(fā)生一些改變次员,目的是將和瀏覽器本身(Chrome)相關(guān)的部分拆分為一個(gè)個(gè)不同的服務(wù),服務(wù)化之后友瘤,這些功能既可以放在不同的進(jìn)程里面運(yùn)行也可以合并為一個(gè)單獨(dú)的進(jìn)程運(yùn)行翠肘。
這樣做的主要原因是讓Chrome在不同性能的硬件上有不同的表現(xiàn)。當(dāng)Chrome運(yùn)行在一些性能比較好的硬件時(shí)辫秧,瀏覽器進(jìn)程相關(guān)的服務(wù)會(huì)被放在不同的進(jìn)程運(yùn)行以提高系統(tǒng)的穩(wěn)定性。相反如果硬件性能不好被丧,這些服務(wù)就會(huì)被放在同一個(gè)進(jìn)程里面執(zhí)行來減少內(nèi)存的占用盟戏。其實(shí)在這次架構(gòu)變化之前,Chrome在Android上面已經(jīng)開始采取類似的做法了甥桂。
<p align="center">Chrome將瀏覽器相關(guān)的服務(wù)放在同一個(gè)進(jìn)程里面運(yùn)行和放在不同的進(jìn)程運(yùn)行的區(qū)別</p>
單幀渲染進(jìn)程 - 網(wǎng)站隔離(Site Isolation)
網(wǎng)站隔離(Site Isolation)是最近Chrome瀏覽器啟動(dòng)的功能柿究,這個(gè)功能會(huì)為網(wǎng)站內(nèi)不同站點(diǎn)的iframe分配一個(gè)獨(dú)立的渲染進(jìn)程。之前說過Chrome會(huì)為每個(gè)tab分配一個(gè)單獨(dú)的渲染進(jìn)程黄选,可是如果一個(gè)tab只有一個(gè)進(jìn)程的話不同站點(diǎn)的iframe都會(huì)跑在這個(gè)進(jìn)程里面蝇摸,這也意味著它們會(huì)共享內(nèi)存婶肩,這就有可能會(huì)破壞同源策略。同源策略是瀏覽器最核心的安全模型貌夕,它可以禁止網(wǎng)站在未經(jīng)同意的情況下去獲取另外一個(gè)站點(diǎn)的數(shù)據(jù)律歼,因此繞過同源策略是很多安全攻擊的主要目的。而進(jìn)程隔離(proces isolation)是隔離網(wǎng)站最好最有效的辦法了啡专。再加上CPU存在Meltdown和Spectre的隱患险毁,網(wǎng)站隔離變得勢(shì)在必行。因此在Chrome 67版本之后们童,桌面版的Chrome會(huì)默認(rèn)開啟網(wǎng)站隔離功能畔况,這樣每一個(gè)跨站點(diǎn)的iframe都會(huì)擁有一個(gè)獨(dú)立的渲染進(jìn)程。
<p align="center">網(wǎng)站隔離功能會(huì)讓跨站的iframe擁有獨(dú)立的進(jìn)程</p>
網(wǎng)站隔離技術(shù)匯聚了我們工程師好幾年的研發(fā)努力慧库,它其實(shí)遠(yuǎn)遠(yuǎn)沒有想象中那樣只是為不同站點(diǎn)的iframe分配一個(gè)獨(dú)立的渲染進(jìn)程那么簡(jiǎn)單跷跪,因?yàn)樗鼜母旧细淖兞烁鱾€(gè)iframe之間的通信方式。網(wǎng)站隔離后齐板,對(duì)于有iframe的網(wǎng)站吵瞻,當(dāng)用戶打開右邊的devtool時(shí),Chrome瀏覽器其實(shí)要做很多幕后工作才能讓開發(fā)者感覺不出這和之前的有什么區(qū)別覆积,這其實(shí)是很難實(shí)現(xiàn)的听皿。對(duì)于一些很簡(jiǎn)單的功能,例如在devtool里面用Ctrl + F鍵在頁(yè)面搜索某個(gè)關(guān)鍵詞宽档,Chrome都要遍歷多個(gè)渲染進(jìn)程去完成尉姨。所以我們的瀏覽器工程師在網(wǎng)站隔離這個(gè)功能發(fā)布后都感嘆這是一個(gè)里程碑式的成就。
總結(jié)
在本篇文章中吗冤,我們探討了瀏覽器高層次的架構(gòu)設(shè)計(jì)以及多進(jìn)程架構(gòu)的帶來的好處又厉。同時(shí)我們還討論了服務(wù)化和網(wǎng)站隔離這些和瀏覽器多進(jìn)程架構(gòu)息息相關(guān)的技術(shù)。在下一篇文章中我們要開始深入了解這些進(jìn)程和線程是如何呈現(xiàn)我們的網(wǎng)站頁(yè)面的了椎瘟。
持續(xù)關(guān)注我的技術(shù)動(dòng)態(tài)
我是進(jìn)擊的大蔥覆致,關(guān)注我和我一起進(jìn)步成獨(dú)當(dāng)一面的全棧工程師!
文章首發(fā)于:窺探現(xiàn)代瀏覽器架構(gòu)(一)
關(guān)注我的個(gè)人公眾號(hào)獲取我的最新技術(shù)推送肺蔚!
[圖片上傳失敗...(image-af8518-1577273453499)]