1. 瀏覽器是多程序的
GPU程序
最多一個,用於3D繪製等
Browser程序
負責瀏覽器介面顯示,與使用者互動。如前進,後退等
負責各個頁面的管理,建立和銷燬其他程序
將Renderer程序得到的記憶體中的Bitmap,繪製到使用者介面上
網路資源的管理,下載等
第三方外掛程序
每種型別的外掛對應一個程序,僅當使用該外掛時才建立
瀏覽器渲染程序(瀏覽器核心)
預設每個tab頁一個程序
頁面渲染,指令碼執行,事件處理等
2. 瀏覽器渲染程序是多執行緒的
GUI渲染執行緒
負責渲染瀏覽器介面,解析HTML,CSS,構建DOM樹和RenderObject樹,佈局和繪製等。
當介面需要重繪(Repaint)或由於某種操作引發迴流(reflow)時,該執行緒就會執行
注意,GUI渲染執行緒與JS引擎執行緒是互斥的,當JS引擎執行時GUI執行緒會被掛起(相當於被凍結了),GUI更新會被儲存在一個佇列中等到JS引擎空閒時立即被執行。
js引擎執行緒
也稱為JS核心,負責處理Javascript指令碼程式。(例如V8引擎)
JS引擎執行緒負責解析Javascript指令碼,執行程式碼。
JS引擎一直等待任務佇列中任務的到來,然後加以處理,一個Tab頁(renderer程序)中只有一個JS執行緒在執行
同樣注意,GUI渲染執行緒與JS引擎執行緒是互斥的。所以如果JS執行的時間過長,要放在body下面,否則就會導致頁面渲染載入阻塞。
事件觸發執行緒
管理著事件佇列
監聽事件,符合條件時把回撥函式放入事件佇列中
定時觸發器執行緒
setInterval與setTimeout在此執行緒中計時完畢後,把回撥函式放入事件佇列中
瀏覽器定時計數器並不是由JavaScript引擎計數的,(因為JavaScript引擎是單執行緒的, 如果處於阻塞執行緒狀態就會影響記計時的準確),因此透過單獨執行緒來計時並觸發定時(計時完畢後,新增到事件佇列中,等待JS引擎空閒後執行)
注意,W3C在HTML標準中規定,規定要求setTimeout中低於4ms的時間間隔算為4ms。
非同步http請求執行緒
檢測到XHR物件狀態變化時,將回調函式放入事件佇列中
event loop整體流程
3. repaint、reflow
repaint
repiant或者redraw遍歷所有的節點檢測各節點的可見性、顏色、輪廓等可見的樣式屬性,然後根據檢測的結果更新頁面的響應部分。
當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響佈局的,比如background-color。則就叫稱為重繪
reflow
reflow指的是計算頁面佈局。某個節點reflow時會重新計算節點的尺寸和位置,而且還有可能觸發其子節點、祖先節點和頁面上的其他節點reflow。在這之後再觸發一次repaint。
當render tree中的一部分(或全部)因為元素的規模尺寸,佈局,隱藏等改變而需要重新構建。這就稱為迴流,每個頁面至少需要一次迴流,就是在頁面第一次載入的時候。
導致reflow的操作
調整視窗大小
改變字型
增加或者移除樣式表
內容變化,比如使用者在input框中輸入文字
啟用 CSS 偽類,比如 :hover (IE 中為兄弟結點偽類的啟用)
操作 class 屬性
指令碼操作 DOM
計算 offsetWidth 和 offsetHeight 屬性
設定 style 屬性的值
它們會大大影響web效能,如何減少reflow、repaint
不要透過父級來改變子元素樣式,最好直接改變子元素樣式,改變子元素樣式儘可能不要影響父元素和兄弟元素的大小和尺寸
儘量透過class來設計元素樣式,切忌用style多次操作單個屬性
實現元素的動畫,對於經常要進行迴流的元件,要抽離出來,它的position屬性應當設為fixed或absolute
權衡速度的平滑。比如實現一個動畫,以1個畫素為單位移動這樣最平滑,但reflow就會過於頻繁,CPU很快就會被完全佔用。如果以3個畫素為單位移動就會好很多。
不要用tables佈局的另一個原因就是tables中某個元素一旦觸發reflow就會導致table裡所有的其它元素reflow。在適合用table的場合,可以設定table-layout為auto或fixed,
這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響範圍。
css裡不要有表示式expression
減少不必要的 DOM 層級(DOM depth)。改變 DOM 樹中的一級會導致所有層級的改變,上至根部,下至被改變節點的子節點。這導致大量時間耗費在執行 reflow 上面。
避免不必要的複雜的 CSS 選擇器,尤其是後代選擇器(descendant selectors),因為為了匹配選擇器將耗費更多的 CPU。
請求如下值offsetTop, offsetLeft, offsetWidth, offsetHeight,scrollTop/Left/Width/Height,clientTop/Left/Width/Height,瀏覽器會發生reflow,建議將他們合併到一起操作,可以減少迴流的次數。
1. 瀏覽器是多程序的
GPU程序
最多一個,用於3D繪製等
Browser程序
負責瀏覽器介面顯示,與使用者互動。如前進,後退等
負責各個頁面的管理,建立和銷燬其他程序
將Renderer程序得到的記憶體中的Bitmap,繪製到使用者介面上
網路資源的管理,下載等
第三方外掛程序
每種型別的外掛對應一個程序,僅當使用該外掛時才建立
瀏覽器渲染程序(瀏覽器核心)
預設每個tab頁一個程序
頁面渲染,指令碼執行,事件處理等
2. 瀏覽器渲染程序是多執行緒的
GUI渲染執行緒
負責渲染瀏覽器介面,解析HTML,CSS,構建DOM樹和RenderObject樹,佈局和繪製等。
當介面需要重繪(Repaint)或由於某種操作引發迴流(reflow)時,該執行緒就會執行
注意,GUI渲染執行緒與JS引擎執行緒是互斥的,當JS引擎執行時GUI執行緒會被掛起(相當於被凍結了),GUI更新會被儲存在一個佇列中等到JS引擎空閒時立即被執行。
js引擎執行緒
也稱為JS核心,負責處理Javascript指令碼程式。(例如V8引擎)
JS引擎執行緒負責解析Javascript指令碼,執行程式碼。
JS引擎一直等待任務佇列中任務的到來,然後加以處理,一個Tab頁(renderer程序)中只有一個JS執行緒在執行
同樣注意,GUI渲染執行緒與JS引擎執行緒是互斥的。所以如果JS執行的時間過長,要放在body下面,否則就會導致頁面渲染載入阻塞。
事件觸發執行緒
管理著事件佇列
監聽事件,符合條件時把回撥函式放入事件佇列中
定時觸發器執行緒
setInterval與setTimeout在此執行緒中計時完畢後,把回撥函式放入事件佇列中
瀏覽器定時計數器並不是由JavaScript引擎計數的,(因為JavaScript引擎是單執行緒的, 如果處於阻塞執行緒狀態就會影響記計時的準確),因此透過單獨執行緒來計時並觸發定時(計時完畢後,新增到事件佇列中,等待JS引擎空閒後執行)
注意,W3C在HTML標準中規定,規定要求setTimeout中低於4ms的時間間隔算為4ms。
非同步http請求執行緒
檢測到XHR物件狀態變化時,將回調函式放入事件佇列中
event loop整體流程
3. repaint、reflow
repaint
repiant或者redraw遍歷所有的節點檢測各節點的可見性、顏色、輪廓等可見的樣式屬性,然後根據檢測的結果更新頁面的響應部分。
當render tree中的一些元素需要更新屬性,而這些屬性只是影響元素的外觀,風格,而不會影響佈局的,比如background-color。則就叫稱為重繪
reflow
reflow指的是計算頁面佈局。某個節點reflow時會重新計算節點的尺寸和位置,而且還有可能觸發其子節點、祖先節點和頁面上的其他節點reflow。在這之後再觸發一次repaint。
當render tree中的一部分(或全部)因為元素的規模尺寸,佈局,隱藏等改變而需要重新構建。這就稱為迴流,每個頁面至少需要一次迴流,就是在頁面第一次載入的時候。
導致reflow的操作
調整視窗大小
改變字型
增加或者移除樣式表
內容變化,比如使用者在input框中輸入文字
啟用 CSS 偽類,比如 :hover (IE 中為兄弟結點偽類的啟用)
操作 class 屬性
指令碼操作 DOM
計算 offsetWidth 和 offsetHeight 屬性
設定 style 屬性的值
它們會大大影響web效能,如何減少reflow、repaint
不要透過父級來改變子元素樣式,最好直接改變子元素樣式,改變子元素樣式儘可能不要影響父元素和兄弟元素的大小和尺寸
儘量透過class來設計元素樣式,切忌用style多次操作單個屬性
實現元素的動畫,對於經常要進行迴流的元件,要抽離出來,它的position屬性應當設為fixed或absolute
權衡速度的平滑。比如實現一個動畫,以1個畫素為單位移動這樣最平滑,但reflow就會過於頻繁,CPU很快就會被完全佔用。如果以3個畫素為單位移動就會好很多。
不要用tables佈局的另一個原因就是tables中某個元素一旦觸發reflow就會導致table裡所有的其它元素reflow。在適合用table的場合,可以設定table-layout為auto或fixed,
這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響範圍。
css裡不要有表示式expression
減少不必要的 DOM 層級(DOM depth)。改變 DOM 樹中的一級會導致所有層級的改變,上至根部,下至被改變節點的子節點。這導致大量時間耗費在執行 reflow 上面。
避免不必要的複雜的 CSS 選擇器,尤其是後代選擇器(descendant selectors),因為為了匹配選擇器將耗費更多的 CPU。
請求如下值offsetTop, offsetLeft, offsetWidth, offsetHeight,scrollTop/Left/Width/Height,clientTop/Left/Width/Height,瀏覽器會發生reflow,建議將他們合併到一起操作,可以減少迴流的次數。