瀏覽器垃圾回收機(jī)制

前言

瀏覽器垃圾回收機(jī)制 GC(Garbage Collecation):垃圾收集器會(huì)定期(周期性)找出那些不在繼續(xù)使用的變量,然后釋放其內(nèi)存。

JS 回收機(jī)制

1. 標(biāo)記清除

當(dāng)變量進(jìn)入環(huán)境時(shí),將變量標(biāo)記"進(jìn)入環(huán)境",當(dāng)變量離開環(huán)境時(shí),標(biāo)記為:"離開環(huán)境"。某一個(gè)時(shí)刻,垃圾回收器會(huì)過濾掉環(huán)境中的變量,以及被環(huán)境變量引用的變量,剩下的就是被視為準(zhǔn)備回收的變量。IE、Firefox、Opera、Chrome、Safari 的 js 實(shí)現(xiàn)使用的都是標(biāo)記清除的垃圾回收策。

2. 引用計(jì)數(shù)

變量的引用次數(shù),被引用一次則加 1,當(dāng)這個(gè)引用計(jì)數(shù)為 0 時(shí),被視為準(zhǔn)備回收的對(duì)象。

瀏覽器內(nèi)存管理

GC 方案

1. 標(biāo)記內(nèi)存中的可達(dá)值

從根節(jié)點(diǎn)出發(fā),遍歷所有的對(duì)象,能訪問到的,標(biāo)記為可達(dá)的,否則為不可達(dá)。

2. 回收不可達(dá)值占據(jù)的內(nèi)存

步驟 1 完成后,清理掉不可達(dá)的對(duì)象。

3. 內(nèi)存整理

步驟 2 完成后,進(jìn)行內(nèi)存碎片整理。

GC 不足

瀏覽器進(jìn)行垃圾回收的時(shí)候,會(huì)暫停 JavaScript 腳本,等垃圾回收完畢再繼續(xù)執(zhí)行其他代碼。對(duì)于 JS 游戲、動(dòng)畫對(duì)連貫性要求比較高的應(yīng)用,如果暫停時(shí)間很長(zhǎng)就會(huì)造成頁(yè)面卡頓。

GC 優(yōu)化策略

1. 分代收集

多回收新生代,少回收老生代。

2. 增量收集

將垃圾收集工作分成更小的塊,每次處理一部分,多次處理。

3. 閑時(shí)收集

在 CPU 空閑時(shí)運(yùn)行,減少對(duì)代碼的影響。

內(nèi)存泄露

內(nèi)存泄露是指一塊被分配的內(nèi)存既不能使用,又不能回收,直到瀏覽器進(jìn)程結(jié)束

常見內(nèi)存泄漏情況:

  • 全局變量
  • 閉包
  • DOM 元素引用
  • 定時(shí)器、回調(diào)
  • 子元素存在引用
  • 監(jiān)聽事件沒有解綁

V8 引擎 GC

V8 的 GC 策略主要基于分代式垃圾回收機(jī)制,根據(jù)對(duì)象的存活時(shí)間進(jìn)行不同的分代,分別采用不同的垃圾回收算法。

1. V8 的內(nèi)存結(jié)構(gòu)

垃圾回收的過程主要出現(xiàn)在新生代和老生代

帶斜紋的區(qū)域代表暫未使用的內(nèi)存:

①. 新生代(new_space)

新生代主要用于存放存活時(shí)間較短的對(duì)象,其兩個(gè) semispace(半空間)構(gòu)成的,內(nèi)存最大值在 64 位系統(tǒng)和 32 位系統(tǒng)上分別為 32MB 和 16MB,在新生代的垃圾回收過程中主要采用了 Scavenge 算法。

(1). Scavenge 算法

Scavenge 算法是一種典型的犧牲空間換取時(shí)間的算法,兩個(gè)空間中,始終只有一個(gè)處于使用狀態(tài),另一個(gè)處于閑置狀態(tài)。當(dāng)進(jìn)行垃圾回收時(shí):

如果 From 空間中尚有存活對(duì)象,則會(huì)被復(fù)制到 To 空間進(jìn)行保存,非存活的對(duì)象會(huì)被自動(dòng)回收。

當(dāng)復(fù)制完成后,F(xiàn)rom 空間和 To 空間完成一次角色互換,To 空間會(huì)變?yōu)樾碌?From 空間,原來(lái)的 From 空間則變?yōu)?To 空間。

Ⅰ. From 空間中分配了三個(gè)對(duì)象 A、B、C

Ⅱ. 當(dāng)程序主線程任務(wù)第一次執(zhí)行完畢后進(jìn)入垃圾回收時(shí),發(fā)現(xiàn)對(duì)象 A 已經(jīng)沒有其他引用,則表示可以對(duì)其進(jìn)行回收

Ⅲ. 對(duì)象 B 和對(duì)象 C 此時(shí)依舊處于活躍狀態(tài),因此會(huì)被復(fù)制到 To 空間中進(jìn)行保存

Ⅳ. 接下來(lái)將 From 空間中的所有非存活對(duì)象全部清除

Ⅴ. 此時(shí) From 空間中的內(nèi)存已經(jīng)清空,開始和 To 空間完成一次角色互換

Ⅵ. 當(dāng)程序主線程在執(zhí)行第二個(gè)任務(wù)時(shí),在 From 空間中分配了一個(gè)新對(duì)象 D

Ⅶ. 任務(wù)執(zhí)行完畢后再次進(jìn)入垃圾回收,發(fā)現(xiàn)對(duì)象 D 已經(jīng)沒有其他引用,表示可以對(duì)其進(jìn)行回收

Ⅷ. 對(duì)象 B 和對(duì)象 C 此時(shí)依舊處于活躍狀態(tài),再次被復(fù)制到 To 空間中進(jìn)行保存

Ⅸ. 再次將 From 空間中的所有非存活對(duì)象全部清除

Ⅹ. From 空間和 To 空間繼續(xù)完成一次角色互換

Scavenge 算法過程:將存活對(duì)象在 From 空間和 To 空間之間進(jìn)行復(fù)制,同時(shí)完成兩個(gè)空間之間的角色互換,其缺點(diǎn)是:浪費(fèi)了一半的內(nèi)存用于復(fù)制。

(2). 對(duì)象晉升

當(dāng)一個(gè)對(duì)象在經(jīng)過多次復(fù)制之后依舊存活,那么它會(huì)被認(rèn)為是一個(gè)生命周期較長(zhǎng)的對(duì)象,在下一次進(jìn)行垃圾回收時(shí),該對(duì)象會(huì)被直接轉(zhuǎn)移到老生代中。

晉升的條件:

  • 經(jīng)歷過一次 Scavenge 算法

  • To 空間的內(nèi)存占比超過 25%

②. 老生代(old_space)

老生代中管理著大量的存活對(duì)象,采用 Mark-Sweep(標(biāo)記清除)和 Mark-Compact(標(biāo)記整理)來(lái)進(jìn)行管理內(nèi)存。

(1). Mark-Sweep 算法

Mark-Sweep(標(biāo)記清除)分為標(biāo)記和清除兩個(gè)階段,

  • 標(biāo)記階段,遍歷堆中的所有對(duì)象,然后標(biāo)記活著的對(duì)象
  • 清除階段,將死亡的對(duì)象進(jìn)行清除

(2). 根節(jié)點(diǎn)

  • 全局對(duì)象
  • 本地函數(shù)的局部變量和參數(shù)
  • 當(dāng)前嵌套調(diào)用鏈上的其他函數(shù)的變量和參數(shù)

③. 大對(duì)象區(qū)(large_object_space)

存放體積超越其他區(qū)域大小的對(duì)象,每個(gè)對(duì)象都會(huì)有自己的內(nèi)存,垃圾回收不會(huì)移動(dòng)大對(duì)象區(qū)。

④. 代碼區(qū)(code_space)

代碼對(duì)象,會(huì)被分配在這里,唯一擁有執(zhí)行權(quán)限的內(nèi)存區(qū)域。

⑤. map 區(qū)(map_space)

存放 Cell 和 Map,每個(gè)區(qū)域都是存放相同大小的元素。

參考

前端之淺談瀏覽器的垃圾回收機(jī)制和內(nèi)存泄露

一文搞懂 V8 引擎的垃圾回收


我的博客


END

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 垃圾數(shù)據(jù) : 有些數(shù)據(jù)被使用之后,可能就不再需要了,我們把這種數(shù)據(jù)稱為垃圾數(shù)據(jù) 為什么要做垃圾回收: 數(shù)據(jù)一直保存...
    老衲不生氣閱讀 2,386評(píng)論 0 3
  • 一、垃圾回收機(jī)制原理 ??由于字符串、對(duì)象和數(shù)組沒有固定大小,所有當(dāng)他們的大小已知時(shí),才能對(duì)他們進(jìn)行動(dòng)態(tài)的存儲(chǔ)分配...
    GoldenSide閱讀 7,924評(píng)論 0 3
  • 當(dāng)需要排查各種內(nèi)存溢出,內(nèi)存泄漏等問題時(shí),當(dāng)垃圾收集成為系統(tǒng)達(dá)到更高并發(fā)的瓶頸時(shí),我們有必要深入GC的原理。 常見...
    AI賀賀閱讀 709評(píng)論 0 1
  • 1、范圍:要回收哪些區(qū)域 在JVM五種內(nèi)存模型中,有三個(gè)是不需要進(jìn)行垃圾回收的:程序計(jì)數(shù)器、JVM棧、本地方法棧。...
    冰河winner閱讀 594評(píng)論 0 2
  • JavaScript引擎的內(nèi)存空間主要分為棧和堆。 棧 棧是臨時(shí)存儲(chǔ)空間,主要存儲(chǔ)局部變量和函數(shù)調(diào)用。 基本類型數(shù)...
    IOneStar閱讀 452評(píng)論 0 0

友情鏈接更多精彩內(nèi)容