瀏覽器多進(jìn)程碑隆,js單線程以及js運(yùn)行機(jī)制
瀏覽器都包含哪些進(jìn)程恭陡?
知道了瀏覽器是多進(jìn)程后,再來看看它到底包含哪些進(jìn)程:(為了簡(jiǎn)化理解上煤,僅列舉主要進(jìn)程)
1.Browser進(jìn)程:瀏覽器的主進(jìn)程(負(fù)責(zé)協(xié)調(diào)休玩、主控),只有一個(gè)劫狠。作用有負(fù)責(zé)瀏覽器界面顯示拴疤,與用戶交互。如前進(jìn)独泞,后退等負(fù)責(zé)各個(gè)頁面的管理呐矾,創(chuàng)建和銷毀其他進(jìn)程將Renderer進(jìn)程得到的內(nèi)存中的Bitmap,繪制到用戶界面上網(wǎng)絡(luò)資源的管理懦砂,下載等
2.第三方插件進(jìn)程:每種類型的插件對(duì)應(yīng)一個(gè)進(jìn)程蜒犯,僅當(dāng)使用該插件時(shí)才創(chuàng)建
3.GPU進(jìn)程:最多一個(gè),用于3D繪制等.
4.瀏覽器渲染進(jìn)程(瀏覽器內(nèi)核)(Renderer進(jìn)程荞膘,內(nèi)部是多線程的):默認(rèn)每個(gè)Tab頁面一個(gè)進(jìn)程罚随,互不影響。主要作用為頁面渲染羽资,腳本執(zhí)行淘菩,事件處理等
強(qiáng)化記憶:在瀏覽器中打開一個(gè)網(wǎng)頁相當(dāng)于新起了一個(gè)進(jìn)程(進(jìn)程內(nèi)有自己的多線程)
瀏覽器內(nèi)核(渲染進(jìn)程)
GUI渲染線程
負(fù)責(zé)渲染瀏覽器界面,解析HTML屠升,CSS瞄勾,構(gòu)建DOM樹和RenderObject樹,布局和繪制等弥激。
當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時(shí)进陡,該線程就會(huì)執(zhí)行
注意,GUI渲染線程與JS引擎線程是互斥的微服,當(dāng)JS引擎執(zhí)行時(shí)GUI線程會(huì)被掛起(相當(dāng)于被凍結(jié)了)趾疚,GUI更新會(huì)被保存在一個(gè)隊(duì)列中等到JS引擎空閑時(shí)立即被執(zhí)行。
JS引擎線程
也稱為JS內(nèi)核,負(fù)責(zé)處理Javascript腳本程序糙麦。(例如V8引擎)
JS引擎線程負(fù)責(zé)解析Javascript腳本辛孵,運(yùn)行代碼。
JS引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來赡磅,然后加以處理魄缚,一個(gè)Tab頁(renderer進(jìn)程)中無論什么時(shí)候都只有一個(gè)JS線程在運(yùn)行JS程序
同樣注意,GUI渲染線程與JS引擎線程是互斥的焚廊,所以如果JS執(zhí)行的時(shí)間過長(zhǎng)冶匹,這樣就會(huì)造成頁面的渲染不連貫,導(dǎo)致頁面渲染加載阻塞咆瘟。
事件觸發(fā)線程
歸屬于瀏覽器而不是JS引擎嚼隘,用來控制事件循環(huán)(可以理解,JS引擎自己都忙不過來袒餐,需要瀏覽器另開線程協(xié)助)
當(dāng)JS引擎執(zhí)行代碼塊如setTimeOut時(shí)(也可來自瀏覽器內(nèi)核的其他線程,如鼠標(biāo)點(diǎn)擊飞蛹、AJAX異步請(qǐng)求等),會(huì)將對(duì)應(yīng)任務(wù)添加到事件線程中
當(dāng)對(duì)應(yīng)的事件符合觸發(fā)條件被觸發(fā)時(shí)灸眼,該線程會(huì)把事件添加到待處理隊(duì)列的隊(duì)尾卧檐,等待JS引擎的處理
注意,由于JS的單線程關(guān)系焰宣,所以這些待處理隊(duì)列中的事件都得排隊(duì)等待JS引擎處理(當(dāng)JS引擎空閑時(shí)才會(huì)去執(zhí)行)
定時(shí)觸發(fā)器線程
傳說中的setInterval與setTimeout所在線程
瀏覽器定時(shí)計(jì)數(shù)器并不是由JavaScript引擎計(jì)數(shù)的,(因?yàn)镴avaScript引擎是單線程的, 如果處于阻塞線程狀態(tài)就會(huì)影響記計(jì)時(shí)的準(zhǔn)確)
因此通過單獨(dú)線程來計(jì)時(shí)并觸發(fā)定時(shí)(計(jì)時(shí)完畢后霉囚,添加到事件隊(duì)列中,等待JS引擎空閑后執(zhí)行)
注意宛徊,W3C在HTML標(biāo)準(zhǔn)中規(guī)定,規(guī)定要求setTimeout中低于4ms的時(shí)間間隔算為4ms逻澳。
異步http請(qǐng)求線程
在XMLHttpRequest在連接后是通過瀏覽器新開一個(gè)線程請(qǐng)求
將檢測(cè)到狀態(tài)變更時(shí)闸天,如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件斜做,將這個(gè)回調(diào)再放入事件隊(duì)列中苞氮。再由JavaScript引擎執(zhí)行。
順序:異步http請(qǐng)求->(產(chǎn)生狀態(tài)變革事件給)->事件觸發(fā)線程(瀏覽器的)->js引擎線程==(互斥)GUI渲染線程
WebWorker與SharedWorker
WebWorker只屬于某個(gè)頁面瓤逼,不會(huì)和其他頁面的Render進(jìn)程(瀏覽器內(nèi)核進(jìn)程)共享
所以Chrome在Render進(jìn)程中(每一個(gè)Tab頁就是一個(gè)render進(jìn)程)創(chuàng)建一個(gè)新的線程來運(yùn)行Worker中的JavaScript程序笼吟。
SharedWorker是瀏覽器所有頁面共享的,不能采用與Worker同樣的方式實(shí)現(xiàn)霸旗,因?yàn)樗浑`屬于某個(gè)Render進(jìn)程贷帮,可以為多個(gè)Render進(jìn)程共享使用
所以Chrome瀏覽器為SharedWorker單獨(dú)創(chuàng)建一個(gè)進(jìn)程來運(yùn)行JavaScript程序,在瀏覽器中每個(gè)相同的JavaScript只存在一個(gè)SharedWorker進(jìn)程诱告,不管它被創(chuàng)建多少次撵枢。
看到這里,應(yīng)該就很容易明白了,本質(zhì)上就是進(jìn)程和線程的區(qū)別锄禽。SharedWorker由獨(dú)立的進(jìn)程管理潜必,WebWorker只是屬于render進(jìn)程下的一個(gè)線程