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 三者中编码。