精华 V8 内存管理机制及垃圾回收
发布于 8 年前 作者 timqian 8538 次浏览 来自 分享

V8 的 Memory Scheme (内存模型)

一个运行中的程序总是与内存中的一部分空间相对应。这部分空间叫做 Resident Set (驻留集)。V8 组织内存的方式与 Java 类似 (如下图)。 v8memoryscheme

其中

  • Code Segment 存放正在被执行的代码
  • Stack 中存放了原始类型变量(比如 Boolean)以及指针(指向存在 Heap 中的 Object 或用于程序的控制流)
  • Heap 中存放了引用类型的变量(比如 Object、String 或 Closure)

在 nodejs 中可以使用 process.memoryUsage() 查看当前程序的内存使用情况。 该函数返回

  1. rss: Resident Set 的大小
  2. heapTotal: 堆的总大小
  3. heapUsed: 实际使用的堆大小

没有返回 Stack 的原因大概是通常因为这部分所占内存比较小(?)

正常的一直运行的代码,内存占用图应该是如下图所示。其中最上面的橙线代表 rss, 中间的红线代表 heapTotal,黄线代表 heapTotal。可以看到黄线随时间变化震荡比较激烈,这是垃圾回收在起作用。

memoryusage

内存的生命周期

  1. 分配内存: 在定义变量,函数;或是调用某些函数(比如 new Date())时分配
  2. 使用分配到的内存(读、写): 使用变量,对变量赋值,调用函数等情况
  3. 不需要时将其释放\归还:垃圾回收

垃圾回收机制

定义:释放某段不再被引用的内存的算法。

现代 js 引擎使用的垃圾回收方法:mark and sweep

这个算法描述起来并不复杂:

假定已知一个根对象(root) (在 js 里,root 就是全局对象)。垃圾回收器会周期性地从 root 开始,寻找所有 root 引用的对象,然后找这些对象引用的对象……从 root 开始,垃圾回收器将找到所有可以获得的对象,然后将无法获得的对象回收。

举个例子来说:

// 定义函数(分配内存)
var run = function () {

  // 定义一个巨大的数组
  var str = new Array(1000000).join('*');

  // 定义一个使用 str 的 闭包
  var doSthWithStr = function () {
    if (str === 'something')
      console.log("Hi there");
  };

  // 调用这个闭包
  doSthWithStr();
};

// 每隔 1 s 调用 run 函数,因此 run 不会被回收。
// 每次调用完 run 之后,由于没有外部对象引用,内部的变量和闭包会被回收
// 所以不会出现内存一直增长的问题。
setInterval(run, 1000);

内存泄漏

定义: 不断使用新的内存,旧的又没有回收,导致程序的内存占用不断增长

例子:稍微改写下上面的代码:

var run = function () {
  var str = new Array(1000000).join('*');
  var doSthWithStr = function () {
  if (str !== 'something')
    console.log("Hi there");
  };
  
  // 由于 doSthWithStr 作为回调函数传给了 setInterval,所以不会被回收
  // 而 str 在它的词法作用域中,并且在函数内部有调用,所以也不会被回收(闭包)
  // 因此内存占用会一直增长
  setInterval(doSthWithStr, 100);
};
setInterval(run, 1000);

你可以把上述代码粘贴到 chrome 的 console 中运行,然后打开 timeline tab,录制内存使用量。你会看到内存使用量以每秒 1 M 的速度增长

Refs

http://apmblog.dynatrace.com/2015/11/04/understanding-garbage-collection-and-hunting-memory-leaks-in-node-js/

http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.html

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management

原文地址

回到顶部