1. 瀏覽器是多進(jìn)程的
GPU進(jìn)程
- 最多一個(gè)暑塑,用于3D繪制等
Browser進(jìn)程
- 負(fù)責(zé)瀏覽器界面顯示腹尖,與用戶交互狮荔。如前進(jìn),后退等
- 負(fù)責(zé)各個(gè)頁面的管理贫贝,創(chuàng)建和銷毀其他進(jìn)程
- 將Renderer進(jìn)程得到的內(nèi)存中的Bitmap秉犹,繪制到用戶界面上
- 網(wǎng)絡(luò)資源的管理蛉谜,下載等
第三方插件進(jìn)程
- 每種類型的插件對(duì)應(yīng)一個(gè)進(jìn)程,僅當(dāng)使用該插件時(shí)才創(chuàng)建
瀏覽器渲染進(jìn)程(瀏覽器內(nèi)核)
- 默認(rèn)每個(gè)tab頁一個(gè)進(jìn)程
- 頁面渲染崇堵,腳本執(zhí)行型诚,事件處理等
2. 瀏覽器渲染進(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)程)中只有一個(gè)JS線程在運(yùn)行
- 同樣注意庆亡,GUI渲染線程與JS引擎線程是互斥的。所以如果JS執(zhí)行的時(shí)間過長捞稿,要放在body下面又谋,否則就會(huì)導(dǎo)致頁面渲染加載阻塞。
事件觸發(fā)線程
- 管理著事件隊(duì)列
- 監(jiān)聽事件娱局,符合條件時(shí)把回調(diào)函數(shù)放入事件隊(duì)列中
定時(shí)觸發(fā)器線程
- setInterval與setTimeout在此線程中計(jì)時(shí)完畢后彰亥,把回調(diào)函數(shù)放入事件隊(duì)列中
- 瀏覽器定時(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請求線程
- 檢測到XHR對(duì)象狀態(tài)變化時(shí),將回調(diào)函數(shù)放入事件隊(duì)列中
3. repaint抹缕、reflow
repaint
- repiant或者redraw遍歷所有的節(jié)點(diǎn)檢測各節(jié)點(diǎn)的可見性澈蟆、顏色、輪廓等可見的樣式屬性卓研,然后根據(jù)檢測的結(jié)果更新頁面的響應(yīng)部分趴俘。
- 當(dāng)render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風(fēng)格寥闪,而不會(huì)影響布局的带膀,比如background-color。則就叫稱為重繪
reflow
- reflow指的是計(jì)算頁面布局橙垢。某個(gè)節(jié)點(diǎn)reflow時(shí)會(huì)重新計(jì)算節(jié)點(diǎn)的尺寸和位置垛叨,而且還有可能觸發(fā)其子節(jié)點(diǎn)、祖先節(jié)點(diǎn)和頁面上的其他節(jié)點(diǎn)reflow柜某。在這之后再觸發(fā)一次repaint嗽元。
- 當(dāng)render tree中的一部分(或全部)因?yàn)樵氐囊?guī)模尺寸,布局喂击,隱藏等改變而需要重新構(gòu)建剂癌。這就稱為回流,每個(gè)頁面至少需要一次回流,就是在頁面第一次加載的時(shí)候翰绊。
導(dǎo)致reflow的操作
- 調(diào)整窗口大小
- 改變字體
- 增加或者移除樣式表
- 內(nèi)容變化佩谷,比如用戶在input框中輸入文字
- 激活 CSS 偽類,比如 :hover (IE 中為兄弟結(jié)點(diǎn)偽類的激活)
- 操作 class 屬性
- 腳本操作 DOM
- 計(jì)算 offsetWidth 和 offsetHeight 屬性
- 設(shè)置 style 屬性的值
它們會(huì)大大影響web性能监嗜,如何減少reflow谐檀、repaint
- 不要通過父級(jí)來改變子元素樣式,最好直接改變子元素樣式裁奇,改變子元素樣式盡可能不要影響父元素和兄弟元素的大小和尺寸
- 盡量通過class來設(shè)計(jì)元素樣式桐猬,切忌用style多次操作單個(gè)屬性
- 實(shí)現(xiàn)元素的動(dòng)畫,對(duì)于經(jīng)常要進(jìn)行回流的組件刽肠,要抽離出來溃肪,它的position屬性應(yīng)當(dāng)設(shè)為fixed或absolute
- 權(quán)衡速度的平滑。比如實(shí)現(xiàn)一個(gè)動(dòng)畫音五,以1個(gè)像素為單位移動(dòng)這樣最平滑惫撰,但reflow就會(huì)過于頻繁,CPU很快就會(huì)被完全占用躺涝。如果以3個(gè)像素為單位移動(dòng)就會(huì)好很多厨钻。
- 不要用tables布局的另一個(gè)原因就是tables中某個(gè)元素一旦觸發(fā)reflow就會(huì)導(dǎo)致table里所有的其它元素reflow。在適合用table的場合诞挨,可以設(shè)置table-layout為auto或fixed莉撇,
- 這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響范圍惶傻。
- css里不要有表達(dá)式expression
- 減少不必要的 DOM 層級(jí)(DOM depth)棍郎。改變 DOM 樹中的一級(jí)會(huì)導(dǎo)致所有層級(jí)的改變,上至根部银室,下至被改變節(jié)點(diǎn)的子節(jié)點(diǎn)涂佃。這導(dǎo)致大量時(shí)間耗費(fèi)在執(zhí)行 reflow 上面励翼。
- 避免不必要的復(fù)雜的 CSS 選擇器,尤其是后代選擇器(descendant selectors)辜荠,因?yàn)闉榱似ヅ溥x擇器將耗費(fèi)更多的 CPU汽抚。
- 盡量不要過多的頻繁的去增加,修改伯病,刪除元素造烁,因?yàn)檫@可能會(huì)頻繁的導(dǎo)致頁面reflow,可以先把該dom節(jié)點(diǎn)抽離到內(nèi)存中進(jìn)行復(fù)雜的操作然后再display到頁面上午笛。
- 請求如下值offsetTop, offsetLeft, offsetWidth, offsetHeight惭蟋,scrollTop/Left/Width/Height,clientTop/Left/Width/Height药磺,瀏覽器會(huì)發(fā)生reflow告组,建議將他們合并到一起操作,可以減少回流的次數(shù)癌佩。