web前端中V8的垃圾回收和內(nèi)存限制如何理解

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

成都創(chuàng)新互聯(lián)公司主營惠水網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,app軟件開發(fā)公司,惠水h5小程序開發(fā)搭建,惠水網(wǎng)站營銷推廣歡迎惠水等地區(qū)企業(yè)咨詢

前言

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

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

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

V8的內(nèi)存限制

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

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

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

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

V8的垃圾回收算法

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

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

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

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

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

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

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

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

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

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

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

新生代中的垃圾回收

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

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

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

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

老生代中的垃圾回收

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

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

增量標記算法和全停頓

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

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

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

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

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

文章標題:web前端中V8的垃圾回收和內(nèi)存限制如何理解
URL鏈接:http://bm7419.com/article30/iidhpo.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設動態(tài)網(wǎng)站、小程序開發(fā)電子商務、網(wǎng)站設計面包屑導航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化