1.線程和進(jìn)程的區(qū)別:
多線程可以并行處理任務(wù)纵苛,但是線程是不能單獨(dú)存在的,它是由進(jìn)程來啟動(dòng)和管理的莹妒。
那什么又是進(jìn)程呢?一個(gè)進(jìn)程就是一個(gè)程序的運(yùn)行實(shí)例绰上。詳細(xì)解釋就是旨怠,啟動(dòng)一個(gè)程序的時(shí)候,操作系統(tǒng)會(huì)為該程序創(chuàng)建一塊內(nèi)存蜈块,用來存放代碼鉴腻、運(yùn)行中的數(shù)據(jù)和一個(gè)執(zhí)行任務(wù)的主線程,我們把這樣的一個(gè)運(yùn)行環(huán)境叫進(jìn)程百揭。為了讓你更好地理解上述計(jì)算過程爽哎,我畫了下面這張對比圖:
從圖中可以看到,線程是依附于進(jìn)程的器一,而進(jìn)程中使用多線程并行處理能提升運(yùn)算效率课锌。
總結(jié)來說,進(jìn)程和線程之間的關(guān)系有以下 4 個(gè)特點(diǎn)。
- 進(jìn)程中的任意一線程執(zhí)行出錯(cuò)渺贤,都會(huì)導(dǎo)致整個(gè)進(jìn)程的崩潰雏胃。
- 線程之間共享進(jìn)程中的數(shù)據(jù)。
- 當(dāng)一個(gè)進(jìn)程關(guān)閉之后志鞍,操作系統(tǒng)會(huì)回收進(jìn)程所占用的內(nèi)存瞭亮。
- 進(jìn)程之間的內(nèi)容相互隔離。
單進(jìn)程瀏覽器時(shí)代
在了解了進(jìn)程和線程之后固棚,我們再來一起看下單進(jìn)程瀏覽器的架構(gòu)统翩。顧名思義,單進(jìn)程瀏覽器是指瀏覽器的所有功能模塊都是運(yùn)行在同一個(gè)進(jìn)程里此洲。
如此多的功能模塊運(yùn)行在一個(gè)進(jìn)程里厂汗,是導(dǎo)致單進(jìn)程瀏覽器不穩(wěn)定、不流暢和不安全的一個(gè)主要因素呜师。下面我就來一一分析下出現(xiàn)這些問題的原因
問題 1:不穩(wěn)定早期瀏覽器需要借助于插件來實(shí)現(xiàn)諸如 Web 視頻面徽、Web 游戲等各種強(qiáng)大的功能,但是插件是最容易出問題的模塊匣掸,并且還運(yùn)行在瀏覽器進(jìn)程之中趟紊,所以一個(gè)插件的意外崩潰會(huì)引起整個(gè)瀏覽器的崩潰。除了插件之外碰酝,渲染引擎模塊也是不穩(wěn)定的霎匈,通常一些復(fù)雜的 JavaScript 代碼就有可能引起渲染引擎模塊的崩潰。和插件一樣送爸,渲染引擎的崩潰也會(huì)導(dǎo)致整個(gè)瀏覽器的崩潰铛嘱。
問題 2:不流暢從上面的“單進(jìn)程瀏覽器架構(gòu)示意圖”可以看出,所有頁面的渲染模塊袭厂、JavaScript 執(zhí)行環(huán)境以及插件都是運(yùn)行在同一個(gè)線程中的墨吓,這就意味著同一時(shí)刻只能有一個(gè)模塊可以執(zhí)行。比如纹磺,下面這個(gè)無限循環(huán)的腳本:function freeze() { while (1) { console.log("freeze"); }}freeze();如果讓這個(gè)腳本運(yùn)行在一個(gè)單進(jìn)程瀏覽器的頁面里帖烘,你感覺會(huì)發(fā)生什么?因?yàn)檫@個(gè)腳本是無限循環(huán)的橄杨,所以當(dāng)其執(zhí)行時(shí)秘症,它會(huì)獨(dú)占整個(gè)線程,這樣導(dǎo)致其他運(yùn)行在該線程中的模塊就沒有機(jī)會(huì)被執(zhí)行式矫。因?yàn)闉g覽器中所有的頁面都運(yùn)行在該線程中乡摹,所以這些頁面都沒有機(jī)會(huì)去執(zhí)行任務(wù),這樣就會(huì)導(dǎo)致整個(gè)瀏覽器失去響應(yīng)采转,變卡頓聪廉。這塊內(nèi)容要繼續(xù)往深的地方講就到頁面的事件循環(huán)系統(tǒng)了,具體相關(guān)內(nèi)容我會(huì)在后面的模塊中為你深入講解。除了上述腳本或者插件會(huì)讓單進(jìn)程瀏覽器變卡頓外板熊,頁面的內(nèi)存泄漏也是單進(jìn)程變慢的一個(gè)重要原因框全。通常瀏覽器的內(nèi)核都是非常復(fù)雜的,運(yùn)行一個(gè)復(fù)雜點(diǎn)的頁面再關(guān)閉頁面邻邮,會(huì)存在內(nèi)存不能完全回收的情況竣况,這樣導(dǎo)致的問題是使用時(shí)間越長克婶,內(nèi)存占用越高筒严,瀏覽器會(huì)變得越慢。
問題 3:不安全這里依然可以從插件和頁面腳本兩個(gè)方面來解釋該原因情萤。插件可以使用 C/C++ 等代碼編寫鸭蛙,通過插件可以獲取到操作系統(tǒng)的任意資源,當(dāng)你在頁面運(yùn)行一個(gè)插件時(shí)也就意味著這個(gè)插件能完全操作你的電腦筋岛。如果是個(gè)惡意插件娶视,那么它就可以釋放病毒、竊取你的賬號密碼睁宰,引發(fā)安全性問題肪获。至于頁面腳本,它可以通過瀏覽器的漏洞來獲取系統(tǒng)權(quán)限柒傻,這些腳本獲取系統(tǒng)權(quán)限之后也可以對你的電腦做一些惡意的事情孝赫,同樣也會(huì)引發(fā)安全問題。以上這些就是當(dāng)時(shí)瀏覽器的特點(diǎn)红符,不穩(wěn)定青柄,不流暢,而且不安全预侯。這是一段不堪回首的過去致开,也許你沒有經(jīng)歷過,不過你可以想象一下這樣的場景:當(dāng)你正在用瀏覽器打開多個(gè)頁面時(shí)萎馅,突然某個(gè)頁面崩潰了或者失去響應(yīng)双戳,隨之而來的是整個(gè)瀏覽器的崩潰或者無響應(yīng)。
目前多進(jìn)程架構(gòu)
不過 Chrome 的發(fā)展是滾滾向前的糜芳,相較之前拣技,目前的架構(gòu)又有了很多新的變化。我們先看看最新的 Chrome 進(jìn)程架構(gòu)耍目,你可以參考下圖:
從圖中可以看出膏斤,最新的 Chrome 瀏覽器包括:1 個(gè)瀏覽器(Browser)主進(jìn)程、1 個(gè) GPU 進(jìn)程邪驮、1 個(gè)網(wǎng)絡(luò)(NetWork)進(jìn)程莫辨、多個(gè)渲染進(jìn)程和多個(gè)插件進(jìn)程。
下面我們來逐個(gè)分析下這幾個(gè)進(jìn)程的功能。
- 瀏覽器進(jìn)程沮榜。主要負(fù)責(zé)界面顯示盘榨、用戶交互、子進(jìn)程管理蟆融,同時(shí)提供存儲等功能草巡。
- 渲染進(jìn)程。核心任務(wù)是將 HTML型酥、CSS 和 JavaScript 轉(zhuǎn)換為用戶可以與之交互的網(wǎng)頁山憨,排版引擎 Blink 和 JavaScript 引擎 V8 都是運(yùn)行在該進(jìn)程中,默認(rèn)情況下弥喉,Chrome 會(huì)為每個(gè) Tab 標(biāo)簽創(chuàng)建一個(gè)渲染進(jìn)程郁竟。出于安全考慮,渲染進(jìn)程都是運(yùn)行在沙箱模式下由境。
- GPU 進(jìn)程棚亩。其實(shí),Chrome 剛開始發(fā)布的時(shí)候是沒有 GPU 進(jìn)程的虏杰。而 GPU 的使用初衷是為了實(shí)現(xiàn) 3D CSS 的效果讥蟆,只是隨后網(wǎng)頁、Chrome 的 UI 界面都選擇采用 GPU 來繪制纺阔,這使得 GPU 成為瀏覽器普遍的需求瘸彤。最后,Chrome 在其多進(jìn)程架構(gòu)上也引入了 GPU 進(jìn)程州弟。
- 網(wǎng)絡(luò)進(jìn)程钧栖。主要負(fù)責(zé)頁面的網(wǎng)絡(luò)資源加載,之前是作為一個(gè)模塊運(yùn)行在瀏覽器進(jìn)程里面的婆翔,直至最近才獨(dú)立出來拯杠,成為一個(gè)單獨(dú)的進(jìn)程。
- 插件進(jìn)程啃奴。主要是負(fù)責(zé)插件的運(yùn)行潭陪,因插件易崩潰,所以需要通過插件進(jìn)程來隔離最蕾,以保證插件進(jìn)程崩潰不會(huì)對瀏覽器和頁面造成影響依溯。
不過凡事都有兩面性,雖然多進(jìn)程模型提升了瀏覽器的穩(wěn)定性瘟则、流暢性和安全性黎炉,但同樣不可避免地帶來了一些問題:
更高的資源占用。因?yàn)槊總€(gè)進(jìn)程都會(huì)包含公共基礎(chǔ)結(jié)構(gòu)的副本(如 JavaScript 運(yùn)行環(huán)境)醋拧,這就意味著瀏覽器會(huì)消耗更多的內(nèi)存資源慷嗜。
更復(fù)雜的體系架構(gòu)淀弹。瀏覽器各模塊之間耦合性高、擴(kuò)展性差等問題庆械,會(huì)導(dǎo)致現(xiàn)在的架構(gòu)已經(jīng)很難適應(yīng)新的需求了薇溃。
對于上面這兩個(gè)問題,Chrome 團(tuán)隊(duì)一直在尋求一種彈性方案缭乘,既可以解決資源占用高的問題沐序,也可以解決復(fù)雜的體系架構(gòu)的問題。