V8內存機制
- 常規而言,64位系統可用內存爲1.4G,32位爲0.7G,以 1.5 GB 的垃圾回收堆內存爲例,最快也要 50毫秒,全量GC 須要 1 秒以上
內存組成
內存分爲新生代的內存空間和老生帶的內存空間node
新生代內存空間
- 設置指令: node --max-new-space-size // 默認1024 KB
- 64位系統爲32MB 32位系統16M
Scavenga 算法
- 將內存分爲 from 和 to , 先將對象分配在 from 中,在進行垃圾回收的時候,將存活的對象,從 form 複製到 to 中(若是to空間佔用已經超過 25% ,則直接進入老生帶內存空間),複製完以後,釋放 from 。同時 to 空間做爲下一個 from 空間。每個已經從 from->to 空間的對象,再下一次GC以後,若是已經經歷過 Scavenga 算法,將進入老生帶內存空間而非 to 空間
老生代內存空間
- 設置指令: node --max-old-space-size // 默認1700 MB
- 經歷過 Scavenga 算法的對象,一般是活對象居多,每次只須要清除少許的死對象。
Mark-Sweep & Mark-Compact 算法
Mark-Sweep 標記清除
- 進行一次標記清楚回收以後,內存空間會出現不連續的狀態,這種內存碎片會對後續的內存分配形成問題,由於極可能出現須要分配一個大對象的狀況,這時全部的碎片空間都沒法完成這次分配,就觸發不必垃圾回收。所以,Mark-Compact 算法被提出來。
Mark-Compact 標記整理
在空間不足以對新生代晉升過來的對象進行分配時,才使用 Mark-Compact算法
- 對象再標記死亡以後,在整理的過程當中,將活着的對象往一端移動,移動完成後,直接清理掉邊界外的內存
Incremental Marking 增量標記
爲了下降全堆垃圾回收帶來的停頓,V8 先從標記階段入手,將本來要一口氣停頓完成的動做改成增量標記,也就是拆分爲許多小「步進」,沒作完一「進步」,就讓 js 應用邏輯執行一小會兒,垃圾回收和應用邏輯交替執行直到標記階段完成。ui
lazy-sweeping 延遲清理
increamental-compaction 增量式整理
並行標記
並行清理
Buffer
- Buffer對象的內存分配不是在V8的堆內存中,而是在Node的C++層面實現內存的申請。
- 由於在處理大量的字節數據,不能採用須要一點內存就向操做系統申請一點內存的方式,這可能形成大量的內存申請的系統調用,對操做系統有必定壓力。
slab 分配機制
createReadStream 使用用例
var fs=require('fs')
var rs =fs.createReadStream('GC.md')
var d =''
rs.on('data',(e)=>{
d+=e
})
rs.on('end',()=>{
console.log(d)
})
複製代碼
d+=e => d=d.toString()+e.toString()編碼
若是打開註釋的內容,將會出現 ❓spa
- 緣由是,文件讀取時一部分一部分讀,若是中途折斷了,原先屬於那個字符的字節,將會被劃分到下一個流中讀取,原先的字節就丟失了,形成解碼失敗。
- 處理截斷的話,本質是用的 decoder 對象,將以前截斷的部分存下來,與下一個流進行拼接。目前只能完成utf-8,base64,ucs-2/utf-16lf 三者中編碼。