Knockout ViewModel计算垃圾收集 [英] Knockout ViewModel computed garbage collection

查看:91
本文介绍了Knockout ViewModel计算垃圾收集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图在我的应用程序代码中跟踪垃圾收集的任何问题。我已经将它剥离为纯粹的knockout代码,并且根据如何创建计算属性收集创建的对象似乎存在问题。



请参阅以下JS小提琴: http://jsfiddle.net/SGXJG/


  1. 打开Chrome分析器。

  2. 创建堆快照

  3. 单击全部

  4. 获取另一个堆快照

  5. 比较快照

  6. Test2& Test3仍然保留在内存中,同时Test1被正确收集。

请参阅以下代码以获取视图模型:

  function ViewModel(){
this.test1 = null;
this.test2 = null;
this.test3 = null;
}
ViewModel.prototype = {
makeAll:function(){
this.make1();
this.make2();
this.make3();
},
make1:function(){
this.test1 = new Test1();
this.test1.kill();
删除this.test1;
},
make2:function(){
this.test2 = new Test2();
this.test2.kill();
删除this.test2;
},
make3:function(){
this.test3 = new Test3();
this.test3.kill();
删除this.test3;
},
};
ko.applyBindings(new ViewModel());

以下是三个测试类:

  function Test1(){
var one = this.one = ko.observable();
var two = this.two = ko.observable();
this.three = ko.computed(function(){
return one()&& two();
});
}
Test1.prototype = {
kill:function(){
this.three.dispose();
}
};

函数Test2(){
this.one = ko.observable();
this.two = ko.observable();
this.three = ko.computed(function(){
return this.one()&& this.two();
},this);
}
Test2.prototype = {
kill:function(){
this.three.dispose();
}
};

函数Test3(){
var self = this;
self.one = ko.observable();
self.two = ko.observable();
self.three = ko.computed(function(){
return self.one()&& self.two();
});
self.kill = function(){
self.three.dispose();
};
}

不同的是Test1'three'参考'一'和' '两个'可观察的属性。有人可以解释这里发生了什么吗?我想有关闭包含对象引用的方式,但我不明白为什么



希望我没有错过任何东西。 Chrome浏览器与所有现代浏览器一样,使用标记和标记垃圾收集的扫描算法。从 MDN


该算法假定您知道一组名为根的对象(在JavaScript中,根是全局对象)。垃圾收集器将定期从这些根开始,找到从这些根引用的所有对象,然后从这些根引用所有对象等。从根开始,垃圾收集器将查找所有可到达的对象,并收集所有非易失性对象,可访问的对象。

垃圾收集器不会立即运行,这就是为什么即使您仍然可以看到Chrome快照中的对象已解除引用(编辑:如此处所述,运行堆快照首先运行垃圾回收器,可能它没有处理所有东西,所以不清除对象;见下文)。

有一件事情似乎一般会触发垃圾收集器将创建新的对象。我们可以使用你的例子来验证。在完成问题中的步骤之后,点击Make1并拍摄另一个堆快照。你应该看到Test2没有了。现在再做一次,你会发现Test3也不见了。



更多注意事项:


  1. 在垃圾回收过程中,Chrome不会清理所有内容。 [Chrome] ...在大多数垃圾回收循环中只处理部分对象堆。 ( google.com )因此,我们看到它需要几次垃圾收集器才能运行清除所有内容。

  2. 只要清除了对象的所有外部引用,该对象最终都会被垃圾回收器清理。在您的示例中,您甚至可以删除 dispose 调用,并且所有对象都将被清除。



I've been trying to track down any issues with garbage collection within my application code. I've stripped it down to pure knockout code and there seems to be an issue collecting created objects depending on how a computed property is created.

Please see the following JS fiddle: http://jsfiddle.net/SGXJG/

  1. Open Chrome profiler.
  2. Take a heap snapshot
  3. Click Make All
  4. Take another heap snapshot
  5. Compare the snapshots
  6. Test2 & Test3 still remain in memory while Test1 is correctly collected.

Please see the following code for the viewmodel:

function ViewModel() {
    this.test1 = null;
    this.test2 = null;
    this.test3 = null;
}
ViewModel.prototype = {
    makeAll: function () {
        this.make1();
        this.make2();
        this.make3();
    },
    make1: function () {
        this.test1 = new Test1();
        this.test1.kill();
        delete this.test1;
    },
    make2: function () {
        this.test2 = new Test2();
        this.test2.kill();
        delete this.test2;
    },
    make3: function () {
        this.test3 = new Test3();
        this.test3.kill();
        delete this.test3;
    },
};
ko.applyBindings(new ViewModel());

And here are the three tests classes:

function Test1() {
    var one = this.one = ko.observable();
    var two = this.two = ko.observable();
    this.three = ko.computed(function () {
        return one() && two();
    });
}
Test1.prototype = {
    kill: function () {
        this.three.dispose();
    }
};

function Test2() {
    this.one = ko.observable();
    this.two = ko.observable();
    this.three = ko.computed(function () {
        return this.one() && this.two();
    }, this);
}
Test2.prototype = {
    kill: function () {
        this.three.dispose();
    }
};

function Test3() {
    var self = this;
    self.one = ko.observable();
    self.two = ko.observable();
    self.three = ko.computed(function () {
        return self.one() && self.two();
    });
    self.kill = function () {
        self.three.dispose();
    };
}

The difference being that Test1 'three' computed does not use this or self to reference the 'one' & 'two' observable properties. Can someone explain what's happening here? I guess there's something in the way the closures contain the object reference but I don't understand why

Hopefully I've not missed anything. Let me know if I have and many thanks for any responses.

解决方案

Chrome, like all modern browsers, uses a mark-and-sweep algorithm for garbage collection. From MDN:

This algorithm assumes the knowledge of a set of objects called roots (In JavaScript, the root is the global object). Periodically, the garbage-collector will start from these roots, find all objects that are referenced from these roots, then all objects referenced from these, etc. Starting from the roots, the garbage collector will thus find all reachable objects and collect all non-reachable objects.

The garbage collector doesn't run right away, which is why you still see the objects in Chrome's snapshot even though you've dereferenced them (edit: As mentioned here, running the heap snapshot first runs the garbage collector. Possibly it's not processing everything and so doesn't clear the objects; see below.)

One thing that seems to generally trigger the garbage collector is to create new objects. We can verify this using your example. After going through the steps in your question, click on "Make1" and take another heap snapshot. You should see that Test2 is gone. Now do it again, and you'll see that Test3 is also gone.

Some more notes:

  1. Chrome doesn't clean up everything during garbage collection. "[Chrome]...processes only part of the object heap in most garbage collection cycles." (google.com) Thus we see that it takes a couple runs of the garbage collector to clear everything.

  2. As long as all external references to a object are cleared, the object will be cleaned up by the garbage collector eventually. In your example, you can even remove the dispose calls, and all the objects will be cleared.

这篇关于Knockout ViewModel计算垃圾收集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆