内存机制

2018-07-17  本文已影响1人  励志摆脱懒癌的少女酱

Node内存由V8进行分配的部分和Node自行分配的部分。

V8的垃圾回收机制与内存限制

V8的内存限制

  因为V8的垃圾回收限制,在node中使用内存:64位系统约1.4G,32位系统约0.7G;因此我们无法读入一个2G的文件读进内存中进行字符串分析处理。
默认情况下:

  1. 64位系统:
    • 老生代内存的最大值是1400MB;
    • 新生代内存的最大值是32MB;
  2. 32位系统:

V8为什么要限制堆的大小?
  V8的垃圾回收机制的限制垃圾回收中会引起js线程暂停执行,V8做一次垃圾回收时间花销较大(以1.5G的垃圾回收堆内存为例,一次小型的垃圾回收需要50ms以上,非增量式的垃圾回收需要1s以上),影响应用的性能和响应能力。

V8的对象分配

  V8中是通过来对所有的js对象进行分配—当我们声明变量并赋值时,所用对象的内存就分配到堆中,若已申请的堆空间内存不够分配新的对象,将继续申请堆内存,直到堆的大小超过V8的限制为止

通过process.memoryUsage()查看V8中内存使用情况:

heapTotal是已申请的堆内存,heapUsed是当前使用的量
V8的堆

V8的垃圾回收机制

scavenge算法:清除new space的内存,牺牲空间换取时间;

Mark-Sweep(标记清除)

Mark-Compact(标记整理)


高效使用内存

作用域(scope):函数调用、with、全局作用域

  1. 标识符查找
       js在执行时会查找该变量定义在哪里,最先查找当前作用域,若当前作用域无法找到该变量的声明,将会向上级的作用域里查找,直到查找到为止。

  2. 作用域链
       标识符的查找会一直沿着作用域链查找到全局作用域,最后抛出未定义错误—查找方向是向上的,因此变量只能向外访问,不能向内访问

  3. 变量的主动释放
      全局变量(不通过var声明或定义在global变量上)需要直到进程退出时才能释放,常驻在老生代中,主动释放的方式:(1)通过delete操作来删除;(2)将变量重新赋值为undefined/null;在接下来的老生代内存清除和整理阶段会被回收释放,以上也适合于非全局变量。

闭包

  实现外部作用域访问内部作用域中变量的方法—利用中间函数叫闭包;
  一旦有变量引用这个中间函数,这个中间函数将不会释放,同时会使原始的作用域不会释放,作用域中产生的内存占用不会得到释放。


内存泄漏

原因及后果

  1. 后果

    • 造成堆积,垃圾回收过程会耗费更多时间进行对象扫描,应用响应缓慢;
    • 进程内存溢出,应用崩溃;
  2. 原因:应当回收的对象出现意外而没有被回收,变成了常驻在老生代中的对象:


大内存应用

  通过stream模块处理大文件—若不需要进行字符串层面的操作,则不需要借助V8来处理;进行纯粹的Buffer操作,就不会受到V8堆内存的限制。

  eg:当我们无法通过fs.readFile()fs.writeFile()直接进行大文件的操作时,可以改用fs.createReadStream()fs.createWriteStream()通过流的方式操作,可读流还提供了pipe()管道方法—封装data事件和写入事件。

内存机制

上一篇 下一篇

猜你喜欢

热点阅读