棧的內存空間是自動分配的,它由系統自動釋放,堆的內存空間是動態分配的,大小不定,不會自動釋放,須要 JS 引擎釋放這些內存。v8 採用的分代式垃圾回收機制。併發
分代式垃圾回收機制
v8 堆內存結構包含新生代內存區,老生代內存區,大對象區,Map 區,代碼區。垃圾回收發生在新生代內存區和老生代內存區。線程
從根(window,global)開始,找全部從根開始引用的對象,而後找這些對象引用的對象……,一直遞歸,被找到的對象就是活動對象,從根往下找不到的對象就是未活動對象,能夠被回收。對象
新生代
存儲空間小,垃圾回收頻繁遞歸
- 新生代空間分爲半個 From 空間,半個 To 空間
- 聲明的對象首先分配到 From 空間。
- 垃圾回收時,複製 From 空間的活動對象到 To 空間。留在From空間的非活動對象會被自動回收
- 複製完成後,From 空間和 To 空間完成互換。To 空間變成新的 From 空間,From 空間變成新的 To 空間。
老生代
存儲空間大,存放存活時間較久的對象內存
- 新生代的對象通過屢次複製後依舊存活(至少經歷過一次複製,且新生代 To 空間的內存佔比超過了 25%),在下一次進行垃圾回收時,該對象直接轉移到老生代中。
- 遍歷堆中全部的對象,標記活動對象,清除未活動對象。
- 對象清除後,在整理的過程當中,會將活動的對象往堆內存的一端進行移動。(碎片整理,方便存放較大的對象)
- 能夠標記或者整理一部分對象,而後暫停,將執行權交給 js 主線程,待主線程空閒時再從原來標記的地方繼續標記或者整理。(不影響主線程運行)
- 也能夠利用增量標記、懶性清理、併發、並行來減小主線程掛起的時間。