国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

淺談瀏覽器多進程與JS線程

Juven / 680人閱讀

摘要:引言一直對瀏覽器的進程線程的運行一無所知,經過一次的刷刷刷相關的博客之后,對其有了初步的了解,是時候該總結一波了。瀏覽器內的進程知道了進程與線程之間的關系之后,下面是瀏覽器與進程的關系了。

引言

一直對瀏覽器的進程、線程的運行一無所知,經過一次的刷刷刷相關的博客之后,對其有了初步的了解,是時候該總結一波了。

進程、線程之間的關系

一個進程有一個或多個線程,線程之間共同完成進程分配下來的任務。打個比方:

假如進程是一個工廠,工廠有它的獨立的資源

工廠之間相互獨立

線程是工廠中的工人,多個工人協作完成任務

工廠內有一個或多個工人

工人之間共享空間

再完善完善概念:

工廠的資源 -> 系統分配的內存(獨立的一塊內存)

工廠之間的相互獨立 -> 進程之間相互獨立

多個工人協作完成任務 -> 多個線程在進程中協作完成任務

工廠內有一個或多個工人 -> 一個進程由一個或多個線程組成

工人之間共享空間 -> 同一進程下的各個線程之間共享程序的內存空間(包括代碼段、數據集、堆等)

進程是cpu資源分配的最小單位(是能擁有資源和獨立運行的最小單位),線程是cpu調度的最小單位(線程是建立在進程的基礎上的一次程序運行單位)。

瀏覽器內的進程

知道了進程與線程之間的關系之后,下面是瀏覽器與進程的關系了。首先,瀏覽器是多進程的,之所以瀏覽器能夠運行,是因為系統給瀏覽器分配了資源,如cpu、內存,簡單的說就是,瀏覽器每打開一個標簽頁,就相當于創建了一個獨立的瀏覽器進程。例如我們查看chrome里面的任務管理器。

注意: 在這里瀏覽器應該也有自己的優化機制,有時候打開多個tab頁后,可以在Chrome任務管理器中看到,有些進程被合并了(譬如打開多個空白標簽頁后,會發現多個空白標簽頁被合并成了一個進程),所以每一個Tab標簽對應一個進程并不一定是絕對的。

除了瀏覽器的標簽頁進程之外,瀏覽器還有一些其他進程來輔助支撐標簽頁的進程,如下:
① Browser進程:瀏覽器的主進程(負責協調、主控),只有一個。作用有

負責瀏覽器界面顯示,與用戶交互。如前進,后退等

負責各個頁面的管理,創建和銷毀其他進程

網絡資源的管理,下載等

② 第三方插件進程:每種類型的插件對應一個進程,僅當使用該插件時才創建
③ GPU進程:最多一個,用于3D繪制等
④ 瀏覽器渲染進程(瀏覽器內核),Renderer進程,內部是多線程的,也就是我們每個標簽頁所擁有的進程,互不影響,負責頁面渲染,腳本執行,事件處理等

如下圖:

瀏覽器內核

瀏覽器內核,即我們的渲染進程,有名Renderer進程,我們頁面的渲染,js的執行,事件的循環都在這一進程內進行,也就是說,該進程下面擁有著多個線程,靠著這些現成共同完成渲染任務。那么這些線程是什么呢,如下:

① 圖形用戶界面GUI渲染線程

負責渲染瀏覽器界面,包括解析HTML、CSS、構建DOM樹、Render樹、布局與繪制等

當界面需要重繪(Repaint)或由于某種操作引發回流(reflow)時,該線程就會執行

② JS引擎線程

JS內核,也稱JS引擎,負責處理執行javascript腳本

等待任務隊列的任務的到來,然后加以處理,瀏覽器無論什么時候都只有一個JS引擎在運行JS程序

③ 事件觸發線程

聽起來像JS的執行,但是其實歸屬于瀏覽器,而不是JS引擎,用來控制時間循環(可以理解,JS引擎自己都忙不過來,需要瀏覽器另開線程協助)

當JS引擎執行代碼塊如setTimeout時(也可來自瀏覽器內核的其他線程,如鼠標點擊、AJAX異步請求等),會將對應任務添加到事件線程中

當對應的事件符合觸發條件被觸發時,該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理

注意:由于JS的單線程關系,所以這些待處理隊列中的事件都得排隊等待JS引擎處理(當JS引擎空閑時才會去執行)

④ 定時觸發器線程

setIntervalsetTimeout所在線程

定時計時器并不是由JS引擎計時的,因為如果JS引擎是單線程的,如果JS引擎處于堵塞狀態,那會影響到計時的準確

當計時完成被觸發,事件會被添加到事件隊列,等待JS引擎空閑了執行

注意:W3C的HTML標準中規定,setTimeout中低與4ms的時間間隔算為4ms

⑤ 異步HTTP請求線程

在XMLHttpRequest在連接后新啟動的一個線程

線程如果檢測到請求的狀態變更,如果設置有回調函數,該線程會把回調函數添加到事件隊列,同理,等待JS引擎空閑了執行

瀏覽器內核,放圖加強記憶:

為什么JS引擎是單線程的

JavaScript作為一門客戶端的腳本語言,主要的任務是處理用戶的交互,而用戶的交互無非就是響應DOM的增刪改,使用事件隊列的形式,一次事件循環只處理一個事件響應,使得腳本執行相對連續。如果JS引擎被設計為多線程的,那么DOM之間必然會存在資源競爭,那么語言的實現會變得非常臃腫,在客戶端跑起來,資源的消耗和性能將會是不太樂觀的,故設計為單線程的形式,并附加一些其他的線程來實現異步的形式,這樣運行成本相對于使用JS多線程來說降低了很多。

瀏覽器內核中線程之間的關系 GUI渲染線程與JS引擎線程互斥

因為JS引擎可以修改DOM樹,那么如果JS引擎在執行修改了DOM結構的同時,GUI線程也在渲染頁面,那么這樣就會導致渲染線程獲取的DOM的元素信息可能與JS引擎操作DOM后的結果不一致。為了防止這種現象,GUI線程與JS線程需要設計為互斥關系,當JS引擎執行的時候,GUI線程需要被凍結,但是GUI的渲染會被保存在一個隊列當中,等待JS引擎空閑的時候執行渲染。
由此也可以推出,如果JS引擎正在進行CPU密集型計算,那么JS引擎將會阻塞,長時間不空閑,導致渲染進程一直不能執行渲染,頁面就會看起來卡頓卡頓的,渲染不連貫,所以,要盡量避免JS執行時間過長。

JS引擎線程與事件觸發線程、定時觸發器線程、異步HTTP請求線程

事件觸發線程、定時觸發器線程、異步HTTP請求線程三個線程有一個共同點,那就是使用回調函數的形式,當滿足了特定的條件,這些回調函數會被執行。這些回調函數被瀏覽器內核理解成事件,在瀏覽器內核中擁有一個事件隊列,這三個線程當滿足了內部特定的條件,會將這些回調函數添加到事件隊列中,等待JS引擎空閑執行。例如異步HTTP請求線程,線程如果檢測到請求的狀態變更,如果設置有回調函數,回調函數會被添加事件隊列中,等待JS引擎空閑了執行。
但是,JS引擎對事件隊列(宏任務)與JS引擎內的任務(微任務)執行存在著先后循序,當每執行完一個事件隊列的時間,JS引擎會檢測內部是否有未執行的任務,如果有,將會優先執行(微任務)。

WebWorker

因為JS引擎是單線程的,當JS執行時間過長會頁面阻塞,那么JS就真的對CPU密集型計算無能為力么?

所以,后來HTML5中支持了 Web Worker。

來自MDN的官方解釋

Web Workers 使得一個Web應用程序可以在與主執行線程分離的后臺線程中運行一個腳本操作。這樣做的好處是可以在一個多帶帶的線程中執行費時的處理任務,從而允許主(通常是UI)線程運行而不被阻塞/放慢。

注意點:

WebWorker可以想瀏覽器申請一個子線程,該子線程服務于主線程,完全受主線程控制。

JS引擎線程與worker線程間通過特定的方式通信(postMessage API,需要通過序列化對象來與線程交互特定的數據)

所以,如果需要進行一些高耗時的計算時,可以多帶帶開啟一個WebWorker線程,這樣不管這個WebWorker子線程怎么密集計算、怎么阻塞,都不會影響JS引擎主線程,只需要等計算結束,將結果通過postMessage傳輸給主線程就可以了。

另外,還有個東西叫 SharedWorker,與WebWorker在概念上所不同。

WebWorker 只屬于某一個頁面,不會和其他標簽頁的Renderer進程共享,WebWorker是屬于Renderer進程創建的進程。

SharedWorker 是由瀏覽器多帶帶創建的進程來運行的JS程序,它被所有的Renderer進程所共享,在瀏覽器中,最多只能存在一個SharedWorker進程。

SharedWorker由進程管理,WebWorker是某一個Renderer進程下的線程。

瀏覽器的渲染流程

每個瀏覽器內核的渲染流程不一樣,下面我們主要以webkit為主。
首先是渲染的前奏:

瀏覽器輸入url,瀏覽器主進程接管,開了一個下載線程

然后進行HTTP請求(DNS查詢、IP尋址等等),等待響應,開始下載響應報文。

將下載完的內容轉交給Renderer進程管理

開始渲染...

在說渲染之前,需要理解一些概念:

DOM Tree: 瀏覽器將HTML解析成樹形的數據結構。

CSS Rule Tree:瀏覽器將CSS解析成樹形的數據結構。

Render Tree:DOM樹和CSS規則樹合并后生產Render樹。

layout:有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關系,從而去計算出每個節點在屏幕中的位置。

painting: 按照算出來的規則,通過顯卡,把內容畫到屏幕上。

reflow(回流):當瀏覽器發現某個部分發生了點變化影響了布局,需要倒回去重新渲染,內行稱這個回退的過程叫 reflow。reflow 會從 這個 root frame 開始遞歸往下,依次計算所有的結點幾何尺寸和位置。reflow 幾乎是無法避免的。現在界面上流行的一些效果,比如樹狀目錄的折疊、展開(實質上是元素的顯 示與隱藏)等,都將引起瀏覽器的 reflow。鼠標滑過、點擊……只要這些行為引起了頁面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會引起它內部、周圍甚至整個頁面的重新渲 染。通常我們都無法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響著。

repaint(重繪):改變某個元素的背景色、文字顏色、邊框顏色等等不影響它周圍或內部布局的屬性時,屏幕的一部分要重畫,但是元素的幾何尺寸沒有變。

注意:display:none的節點不會被加入Render Tree,而visibility: hidden則會,所以display:none會觸發reflowvisibility: hidden會觸發repaint

瀏覽器內核拿到響應報文之后,渲染大概分為以下步驟

解析html生產DOM樹。

解析CSS規則。

根據DOM Tree和CSS Tree生成Render Tree。

根據Render樹進行layout,負責各個元素節點的尺寸、位置計算。

繪制Render樹(painting),繪制頁面像素信息。

瀏覽器會將各層的信息發送給GPU,GPU會將各層合成(composite),顯示在屏幕上。

詳細步驟略去,大概步驟如下,渲染完畢后JS引擎開始執行load事件,繪制流程見下圖。

由圖中可以看出,css在加載過程中不會影響到DOM樹的生成,但是會影響到Render樹的生成,進而影響到layout,所以一般來說,style的link標簽需要盡量放在head里面,因為在解析DOM樹的時候是自上而下的,而css樣式又是通過異步加載的,這樣的話,解析DOM樹下的body節點和加載css樣式能盡可能的并行,加快Render樹的生成的速度,當然,如果css是通過js動態添加進來的,會引起頁面的重繪或重新布局。
從有html標準以來到目前為止(2017年5月),標準一直是規定style元素不應出現在body元素中。

前面提到了load事件,那么與DOMContentLoaded事件有什么分別。

當 DOMContentLoaded 事件觸發時,僅當DOM加載完成,不包括樣式表,圖片。 (譬如如果有async加載的腳本就不一定完成)

當 onLoad 事件觸發時,頁面上所有的DOM,樣式表,腳本,圖片都已經加載完成了。 (渲染完畢了)

順序是:DOMContentLoaded -> load

最后

寫到這里,總結了也有不少的內容,也對瀏覽器多線程、JS引擎有所了解,后面打算在看看JS的運行機制。前端知識也是無窮無盡,數不清的概念與無數個易忘的知識、各種框架原理,學來學去,還是發現自己知道得太少了。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107120.html

相關文章

  • 淺談 JavaScript 運行機制

    摘要:以多線程的形式,允許單個任務分成不同的部分進行運行。提供協調機制,一方面防止進程之間和線程之間產生沖突,另一方面允許進程之間和線程之間共享資源。主線程會不斷的重復上訴過程。 眾所周知,js是單線程的,說到線程,我們首先來仔細辨析一下線程和進程的知識。 一、進程與線程 阮一峰老師的一篇文章寫的很好 cpu會給當前進程分配資源,進程是資源分配的最小單位,進程的資源會分配給線程使用,線程是C...

    URLOS 評論0 收藏0
  • 淺談HTML5 Web Worker

    摘要:事實上,瀏覽器內部的運行機制是,先將通信內容串行化,然后把串行化后的字符串發給子線程,后者再將它還原。當一個的文檔列表中的任何一個對象都是處于完全活動狀態的時候,這個會被稱之為需要激活線程。 瀏覽器中的Web Worker 背景介紹 我們都知道JavaScript這個語言在執行的時候是采用單線程進行執行的,也就是說在同一時間只能做一件事,這也和這門語言有很大的關系,采用同步執行的方式進...

    Tecode 評論0 收藏0
  • 淺談線程

    摘要:線程被稱為輕量級進程。在大多數操作系統中,線程都是最基本的調度單位。在多線程程序中,,還存在由于使用多線程而引入的其他問題。由于多線程訪問無狀態對象的行為不會影響到其他線程中操作的正確性,因此無狀態對象一定是線程安全的。 概述 最近遇到了些并發的問題,恰巧也有朋友問我類似的問題,無奈并發基礎知識過弱,只大概了解使用一些同步機制和并發工具包類,沒有形成一個完整的知識體系,并不能給出一個良...

    Freeman 評論0 收藏0
  • 淺談Python線程

    摘要:進程可創建多個線程來執行同一程序的不同部分。就緒等待線程調度。運行線程正常運行阻塞暫停運行,解除阻塞后進入狀態重新等待調度。消亡線程方法執行完畢返回或者異常終止。多線程多的情況下,依次執行各線程的方法,前頭一個結束了才能執行后面一個。 淺談Python多線程 作者簡介: 姓名:黃志成(小黃)博客: 博客 線程 一.什么是線程? 操作系統原理相關的書,基本都會提到一句很經典的話: 進程...

    zsirfs 評論0 收藏0

發表評論

0條評論

Juven

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<