V8內存處理邏輯

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') // 註釋1 {highWaterMark:11}
// 註釋2 rs.setEncoding('utf8')
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 三者中編碼。
相關文章
相關標籤/搜索