新聞中心
V8 內(nèi)存管理(垃圾回收機制)
V8 也會申請內(nèi)存,申請的內(nèi)存又會分為堆內(nèi)存和棧內(nèi)存

成都創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站設計、成都網(wǎng)站制作與策劃設計,新羅網(wǎng)站建設哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設10年,網(wǎng)設計領(lǐng)域的專業(yè)建站公司;建站業(yè)務涵蓋:新羅等地區(qū)。新羅做網(wǎng)站價格咨詢:18980820575
1.1 棧
- 棧用于存放 JS 中的基本類型和引用類型指針
- 棧的空間是連續(xù)的,增加刪除只需要移動指針,操作速度非???/li>
- 棧的空間是有限的,當棧滿了,就會拋出一個錯誤
- 棧一般是在執(zhí)行函數(shù)時創(chuàng)建的,在函數(shù)執(zhí)行完畢后,棧就會被銷毀
1.2 堆
- 堆主要用于存儲 JS 中的引用類型
1.2.1 堆空間分類
1.2.1.1 新生代(new space)
- 新生代內(nèi)存用于存放一些生命周期比較短的對象數(shù)據(jù)
1.2.1.2 老生代(old space)
- 老生代內(nèi)存用于存放一些生命周期比較長的對象數(shù)據(jù)
- 當new space的對象進行兩個周期的垃圾回收后,如果數(shù)據(jù)還存在new space中,則將他們存放到old space中
- Old Space 使用標記清除和標記整理的方式進行垃圾回收
1.2.2 什么是垃圾
- 在程序運行過程中肯定會用到一些數(shù)據(jù),這些數(shù)據(jù)會放在堆棧中,但是在程序運行結(jié)束后,這些數(shù)據(jù)就不會再被使用了,那些不再使用的數(shù)據(jù)就是垃圾
1.2.3 新生代的垃圾回收
- 新生代內(nèi)存有兩個區(qū)域,分別是對象區(qū)域(from) 和 空閑區(qū)域(to)
- 新生代內(nèi)存使用Scavenger 算法來管理內(nèi)存,垃圾回收的入口廣度優(yōu)先遍歷 From-Space 中的對象,從根對象出發(fā),廣度優(yōu)先遍歷所有能到達的對象,把存活的對象復制到 To-Space遍歷完成后,清空 From-SpaceFrom-Space 和 To-Space 角色互換
- 復制后的對象在 To-Space 中占用的內(nèi)存空間是連續(xù)的,不會出現(xiàn)碎片問題
- 這種垃圾回收方式快速而又高效,但是會造成空間浪費(有 To-Space 空閑區(qū)域)
- 新生代的 GC 比較頻繁
- 新生代的對象轉(zhuǎn)移到老生代稱為晉升 Promote,判斷晉升的情況有兩種經(jīng)過一次 GC 還存活的對象對象復制到 To-Space 時,To-Space 的空間達到一定的限制(超過 25%)
1.2.4 老生代的垃圾回收
V8 在老生代中的垃圾回收策略采用Mark-Sweep(標記清除)和 Mark-Compact(標記整理)相結(jié)合
1.2.4.1 Mark-Sweep(標記清除)
- 標記清除分為標記和清除兩個階段
- 在標記階段需要遍歷(深度優(yōu)先遍歷)堆中的所有對象,并標記那些活著的對象,然后進入清除階段。在清除階段總,只清除沒有被標記的對象
- V8 采取的是黑色和白色來標記數(shù)據(jù),垃圾收集之前,會把所有的數(shù)據(jù)設置為白色,用來標記所有的尚未標記的對象,然后會從 GC 根出發(fā),以深度優(yōu)先的方式把所有的能訪問到的數(shù)據(jù)都標記為黑色,遍歷結(jié)束后黑色的就是活的數(shù)據(jù),白色的就是可以清理的垃圾數(shù)據(jù)
- 由于標記清除只清除死亡對象,而死亡對象在老生代中占用的比例很小,所以效率較高
- 標記清除有一個問題就是進行一次標記清楚后,內(nèi)存空間往往是不連續(xù)的,會出現(xiàn)很多的內(nèi)存碎片。如果后續(xù)需要分配一個需要內(nèi)存空間較多的對象時,如果所有的內(nèi)存碎片都不夠用,就會出現(xiàn)內(nèi)存溢出的問題
1.2.4.2 Mark-Compact(標記整理)
- 標記整理正是為了解決標記清除所帶來的內(nèi)存碎片的問題
- 標記整理在標記清除的基礎(chǔ)進行修改,將其的清除階段變?yōu)榫o縮極端
- 在整理的過程中,將活著的對象向內(nèi)存區(qū)的一段移動,移動完成后直接清理掉邊界外的內(nèi)存
- 緊縮過程涉及對象的移動,所以效率并不是太好,但是能保證不會生成內(nèi)存碎片,一般 10 次標記清理會伴隨一次標記整理
1.2.5 優(yōu)化
- 在執(zhí)行垃圾回收算法期間,JS 腳本需要暫停,這種叫 Stop the world(全停頓)
- 如果回收時間過長,會引起卡頓
- 性能優(yōu)化把大任務拆分小任務,分步執(zhí)行,類似 fiber將一些任務放在后臺執(zhí)行,不占用主線程
JavaScript執(zhí)行 垃圾標記、垃圾清理、垃圾整理 JavaScript執(zhí)行
-------------- ---------------->
1.2.5.1 Parallel(并行執(zhí)行)
- 新生代的垃圾回收采取并行策略提升垃圾回收速度,它會開啟多個輔助線程來執(zhí)行新生代的垃圾回收工作
-------輔助線程----->
-------輔助線程----->
-------輔助線程----->
--------- --------------------------->
1.2.5.2 增量標記
- 老生代因為對象又大又多,所以垃圾回收的時間更長,采用增量標記的方式進行優(yōu)化
- 增量標記就是把標記工作分成多個階段,每個階段都只標記一部分對象,和主線程的執(zhí)行穿插進行
- 為了支持增量標記,V8 必須可以支持垃圾回收的暫停和恢復,所以采用了黑白灰三色標記法黑色表示這個節(jié)點被 GC 根引用到了,而且該節(jié)點的子節(jié)點都已經(jīng)標記完成了灰色表示這個節(jié)點被 GC 根引用到了,但子節(jié)點還沒被垃圾回收器標記處理,也表明目前正在處理這個節(jié)點白色表示此節(jié)點還沒未被垃圾回收器發(fā)現(xiàn),如果在本輪遍歷結(jié)束時還是白色,那么這塊數(shù)據(jù)就會被收回
- 引入了灰色標記后,就可以通過判斷有沒有灰色節(jié)點來判斷標記是否完成了,如果有灰色節(jié)點,下次恢復的應該從灰色節(jié)點繼續(xù)執(zhí)行
---------開始標記---增量標記---增量標記---清理---整理----------------->
1.2.5.3 Write-barrier(寫屏障)
- 當黑色指向白色節(jié)點的時候,就會觸發(fā)寫屏障,這個寫屏障會把白色節(jié)點設置為灰色
global.a = { name: "a" }
global.a.b = { name: "b1" }
//執(zhí)行標記工作
global.a.b = { name: "b2" }
//繼續(xù)執(zhí)行標記工作
1.2.5.4 Lazy Sweeping(惰性清理)
- 當增量標記完成后,如果內(nèi)存夠用,先不清理,等 JS 代碼執(zhí)行完慢慢清理
1.2.5.5 concurrent(并發(fā)回收)
- 其實增量標記和惰性清理并沒有減少暫停的總時間
- 并發(fā)回收就是主線程在執(zhí)行過程中,輔助線程可以在后臺完成垃圾回收工作
- 標記操作全都由輔助線程完,清理操作由主線程和輔助線程配合完成
----輔助線程標記----> -----清理整理---->
----輔助線程標記----> -----清理整理---->
----輔助線程標記----> -----清理整理---->
-----------------------------執(zhí)行JS>-----清理整理--->-------------------------
文章出自:??前端餐廳??,如有轉(zhuǎn)載本文請聯(lián)系前端餐廳ReTech今日頭條號。
github:??https://github.com/zuopf769??
文章題目:V8內(nèi)存管理(垃圾回收機制)
標題路徑:http://www.5511xx.com/article/ccdoioj.html


咨詢
建站咨詢
