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 三者中编码。
相关文章
相关标签/搜索