中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

web前端中V8的垃圾回收和內存限制如何理解

發布時間:2022-01-15 09:47:35 來源:億速云 閱讀:153 作者:柒染 欄目:移動開發

這篇文章將為大家詳細講解有關web前端中V8的垃圾回收和內存限制如何理解,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

前言

在第三次瀏覽器大戰中,來自Google的Chrome瀏覽器憑借優異的性能成為聚光燈下的焦點。而Chrome的成功離不開站在其背后的JavaScript引擎V8。

隨著V8的出現,讓JavaScript徹底擺脫了作為腳本語言性能低下的形象。V8出色的性能讓JavaScript出現在高性能后臺服務程序開發的舞臺上。也正是因為這樣的契機,在2009年,Node的創始人Ryan Dahl選擇了V8作為Node的JavaScript腳本引擎。在事件驅動、非阻塞I/O模型的設計下實現了Node。

但是需要了解的是,Node雖然在JavaScript的執行上受益于V8,極大的擴寬了JavaScript的應用場景,讓其應用場景從客戶端進軍到了服務端,但是也同時受到了v8的限制,對于性能敏感的服務端的程序,內存管理、垃圾回收都會對服務的構成產生影響,而這些都和v8有著很大的關系。

V8的內存限制

在Node中如果通過JavaScript使用內存操作時會發現實際只能使用部分內存(64位系統下約為1.4G,32位系統下約為0.7G),這種限制對于其他的服務端開發語言來說基本上都是不存在的。

而V8的這種限制導致的結果是Node無法直接操作大內存對象。在單個Node進程的情況下,計算機的內存資源無法得到充足的使用。

而問題的原因在于Node是基于V8構建,所以在Node中使用對象都是通過V8自己的方式進行分配和管理。

而其內存管理機制在瀏覽器的場景下問題不大,但是對于Node,卻使得Node有了這般限制。

V8的垃圾回收算法

V8的垃圾回收策略主要基于分代式垃圾回收機制。

在應用中,對象的生存周期長短不一,不同的算法只能針對特定情況產生較為良好的效果。所以在現代的垃圾回收算法中按對象的存活時間將內存的垃圾回收進行不同的分代,然后對不同分代的內存施以更高效的算法。

在V8中,所有的JavaScript對象都是通過堆來進行分配。我們可以通過process.memoryUsage()這個方法返回的heapTotal和heapUsed來查看堆的使用情況,前者是以申請的堆內存,后者是當前使用的量。如果在代碼中使用的對象使用的空間超過了申請的空間,那么就會繼續申請堆內存,直到堆的大小超過V8的限制。

在V8中,主要將堆分為新生代和老生代兩個區域,新生代中存放的是生存時間短的對象,老生代中存放的生存時間久的對象。

新生區通常只支持 1~8M 的容量,而老生區支持的容量就大很多了。對于這兩塊區域,V8 分別使用兩個不同的垃圾回收器,以便更高效地實施垃圾回收。

· 副垃圾回收器,主要負責新生代的垃圾回收。

· 主垃圾回收器,主要負責老生代的垃圾回收。

不論什么類型的垃圾回收器,它們都有一套共同的執行流程。

1. 第一步是標記空間中活動對象和非活動對象。所謂活動對象就是還在使用的對象,非活動對象就是可以進行垃圾回收的對象。

2. 第二步是回收非活動對象所占據的內存。其實就是在所有的標記完成之后,統一清理內存中所有被標記為可回收的對象。

3. 第三步是做內存整理。一般來說,頻繁回收對象后,內存中就會存在大量不連續空間,我們把這些不連續的內存空間稱為內存碎片,。當內存中出現了大量的內存碎片之后,如果需要分配較大連續內存的時候,就有可能出現內存不足的情況。所以最后一步需要整理這些內存碎片。(這步其實是可選的,因為有的垃圾回收器不會產生內存碎片).

新生代中的垃圾回收

新生代中用Scavenge 算法來處理,把新生代空間對半劃分為兩個區域,一半是對象區域,一半是空閑區域。新加入的對象都會存放到對象區域,當對象區域快被寫滿時,就需要執行一次垃圾清理操作。

在垃圾回收過程中,首先要對對象區域中的垃圾做標記;標記完成之后,就進入垃圾清理階段,副垃圾回收器會把這些存活的對象復制到空閑區域中,同時它還會把這些對象有序地排列起來,所以這個復制過程,也就相當于完成了內存整理操作,復制后空閑區域就沒有內存碎片了。

完成復制后,對象區域與空閑區域進行角色翻轉,也就是原來的對象區域變成空閑區域,原來的空閑區域變成了對象區域。這樣就完成了垃圾對象的回收操作,同時這種角色翻轉的操作還能讓新生代中的這兩塊區域無限重復使用下去.

為了執行效率,一般新生區的空間會被設置得比較小,也正是因為新生區的空間不大,所以很容易被存活的對象裝滿整個區域。為了解決這個問題,JavaScript 引擎采用了對象晉升策略,也就是經過兩次垃圾回收依然還存活的對象,會被移動到老生區中。

老生代中的垃圾回收

老生代中用標記 - 清除(Mark-Sweep)的算法來處理。首先是標記過程階段,標記階段就是從一組根元素開始,遞歸遍歷這組根元素(遍歷調用棧),在這個遍歷過程中,能到達的元素稱為活動對象,沒有到達的元素就可以判斷為垃圾數據.然后在遍歷過程中標記,標記完成后就進行清除過程。它和副垃圾回收器的垃圾清除過程完全不同,這個的清除過程是刪除標記數據。

清除算法后,會產生大量不連續的內存碎片。而碎片過多會導致大對象無法分配到足夠的連續內存,于是又產生了標記 - 整理(Mark-Compact)算法,這個標記過程仍然與標記 - 清除算法里的是一樣的,但后續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然后直接清理掉端邊界以外的內存,從而讓存活對象占用連續的內存塊。

增量標記算法和全停頓

由于 JavaScript 是運行在主線程之上的,一旦執行垃圾回收算法,都需要將正在執行的 JavaScript 腳本暫停下來,待垃圾回收完畢后再恢復腳本執行。我們把這種行為叫做全停頓。

在 V8 新生代的垃圾回收中,因其空間較小,且存活對象較少,所以全停頓的影響不大,但老生代就不一樣了。如果執行垃圾回收的過程中,占用主線程時間過久,主線程是不能做其他事情的。比如頁面正在執行一個 JavaScript 動畫,因為垃圾回收器在工作,就會導致這個動畫在垃圾回收過程中無法執行,這將會造成頁面的卡頓現象。

為了降低老生代的垃圾回收而造成的卡頓,V8 將標記過程分為一個個的子標記過程,同時讓垃圾回收標記和 JavaScript 應用邏輯交替進行,直到標記階段完成,我們把這個算法稱為增量標記(Incremental Marking)算法.

使用增量標記算法,可以把一個完整的垃圾回收任務拆分為很多小的任務,這些小的任務執行時間比較短,可以穿插在其他的 JavaScript 任務中間執行,這樣當執行上述動畫效果時,就不會讓用戶因為垃圾回收任務而感受到頁面的卡頓了。

關于web前端中V8的垃圾回收和內存限制如何理解就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

辛集市| 衡山县| 房山区| 福贡县| 同心县| 北川| 兴文县| 龙岩市| 阿拉善左旗| 武胜县| 温宿县| 江川县| 通道| 子长县| 若羌县| 许昌县| 乌苏市| 新巴尔虎左旗| 鹰潭市| 揭东县| 定陶县| 普安县| 观塘区| 唐海县| 富阳市| 油尖旺区| 通化市| 盖州市| 北宁市| 泗水县| 武宣县| 邵东县| 定州市| 屯门区| 宝鸡市| 施甸县| 凌源市| 株洲市| 长顺县| 肃宁县| 宜州市|