【问题标题】:Understanding Mark and Sweep Algorithm in JavaScript了解 JavaScript 中的标记和扫描算法
【发布时间】:2020-02-22 16:24:48
【问题描述】:

根据MDN,Mark and Sweep 是一种比引用计数更好的垃圾收集算法,因为它避免了循环引用可能发生的内存泄漏。但是,我不明白为什么会这样?有人可以(用代码)解释 Mark and Sweep 如何避免此类内存泄漏吗?随意使用来自 MDN 的以下代码,它解释了引用计数的工作原理:

var x = { 
  a: {
    b: 2
  }
}; 

// 2 objects are created. One is referenced by the other as one of its properties.
// The other is referenced by virtue of being assigned to the 'x' variable.
// Obviously, none can be garbage-collected.

var y = x;      // The 'y' variable is the second thing that has a reference to the object.

x = 1;          // Now, the object that was originally in 'x' has a unique reference
                //   embodied by the 'y' variable.

var z = y.a;    // Reference to 'a' property of the object.
                //   This object now has 2 references: one as a property, 
                //   the other as the 'z' variable.

y = 'mozilla';  // The object that was originally in 'x' has now zero
                //   references to it. It can be garbage-collected.
                //   However its 'a' property is still referenced by 
                //   the 'z' variable, so it cannot be freed.

z = null;       // The 'a' property of the object originally in x 
                //   has zero references to it. It can be garbage collected.

另外,全局变量永远不会被垃圾回收吗?

【问题讨论】:

    标签: javascript garbage-collection


    【解决方案1】:

    Mark-sweep 的工作原理是标记根,例如临时变量(在当前方法中)和全局(静态)变量,然后清除堆中所有未标记的引用

    例如,示例中的第一行创建了一个嵌套对象并将其分配给变量 x。为了让 MS 知道它的字段 b 是否存在,它首先标记根。

    这通过检查当前方法(框架)中的所有全局变量和局部变量,然后标记它们指向的引用来工作。例如一个是 x 的外部对象。

    这里必须注意,内部对象布局中的每个对象(至少)保留两个位,用于标记对象是否被引用。

    var x = { a: {b: 2}}; 
    

    因此,包含字段 a 的外部对象被标记为活动的,因为它被局部变量引用。现在它也必须标记其字段引用的对象。字段 a 和 a.b 就是这样的对象。一旦一个对象的字段和它的字段字段引用的所有引用都被标记为外部对象的第二位,它的内部对象被标记。

    为简单起见,我们假设这是堆上唯一的活动对象。一旦标记阶段完成,堆(可以将其想象为通用对象的数组或列表)可以被扫描。因此,所有对象要么完全标记(2 位),要么没有标记,也就是没有引用。所有未标记的对象都可以被释放,它们曾经占用的内存可以重新使用。

    现在循环引用的问题是一个对象a引用另一个对象b,反之亦然。对于引用计数,只要一个对象对自身有引用,它的引用计数字段将至少为 1。问题是没有根对象或由根间接引用的对象(也称为活动对象)引用循环对象,但根据算法,引用计数器等于或大于 1 表示它是活动的。

    Mark-sweep 对活动对象的定义不同,即它被根对象直接或间接引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多