最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Knockout.js consuming too much memory - Stack Overflow

programmeradmin2浏览0评论

I keep Process Explorer open and inspect the "Private Bytes" column of the firefox.exe process. After pressing the "Add" button in this example:

<script id="tmplComment" type="text/x-jquery-tmpl">
    <div>
        <span>Comment:&nbsp;</span>
        <span data-bind="text: $data"></span>
    </div>
</script>    

<input type="button" id="btnAdd" value="Add"/>
<div id="Content" data-bind="template: {name: 'tmplComment', foreach: Comments}">        
</div>

With this code:

var vm = {Comments: ko.observableArray(["a", "b"])};
ko.applyBindings(vm);
$("#btnAdd").click(function()
{
    for(var i = 0; i<500; i++)
        vm.Comments.push(i.toString());
});

(also see this jsfiddle)

I experience that the private bytes taken by Firefox has increased about 50-100 MByte.

The execution time is also rather long when I pare it to implementations lacking dependency tracking, given this example:

<script id="tmplComment" type="text/x-jquery-tmpl">
    <div>
        <span>Comment:&nbsp;</span>
        <span data-bind="text: $data"></span>
    </div>
</script>    

<input type="button" id="btnAdd" value="Add"/>
<div id="Content" data-bind="template: {name: 'tmplComment', foreach: Comments}">        
</div>

With this code:

var vm = {Comments: ko.observableArray(["a", "b"])};
ko.applyBindings(vm);
$("#btnAdd").click(function()
{
    for(var i = 0; i<500; i++)
        vm.Comments.push(i.toString());
});

(also see this jsfiddle)

My question: Is poor performance inherent when using Knockout.js or am I doing something wrong?

I keep Process Explorer open and inspect the "Private Bytes" column of the firefox.exe process. After pressing the "Add" button in this example:

<script id="tmplComment" type="text/x-jquery-tmpl">
    <div>
        <span>Comment:&nbsp;</span>
        <span data-bind="text: $data"></span>
    </div>
</script>    

<input type="button" id="btnAdd" value="Add"/>
<div id="Content" data-bind="template: {name: 'tmplComment', foreach: Comments}">        
</div>

With this code:

var vm = {Comments: ko.observableArray(["a", "b"])};
ko.applyBindings(vm);
$("#btnAdd").click(function()
{
    for(var i = 0; i<500; i++)
        vm.Comments.push(i.toString());
});

(also see this jsfiddle)

I experience that the private bytes taken by Firefox has increased about 50-100 MByte.

The execution time is also rather long when I pare it to implementations lacking dependency tracking, given this example:

<script id="tmplComment" type="text/x-jquery-tmpl">
    <div>
        <span>Comment:&nbsp;</span>
        <span data-bind="text: $data"></span>
    </div>
</script>    

<input type="button" id="btnAdd" value="Add"/>
<div id="Content" data-bind="template: {name: 'tmplComment', foreach: Comments}">        
</div>

With this code:

var vm = {Comments: ko.observableArray(["a", "b"])};
ko.applyBindings(vm);
$("#btnAdd").click(function()
{
    for(var i = 0; i<500; i++)
        vm.Comments.push(i.toString());
});

(also see this jsfiddle)

My question: Is poor performance inherent when using Knockout.js or am I doing something wrong?

Share Improve this question edited Feb 22, 2014 at 19:32 Jeroen 64k47 gold badges228 silver badges366 bronze badges asked Jun 27, 2011 at 20:20 Attila KunAttila Kun 2,4353 gold badges24 silver badges34 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

Setting the memory issue aside for a moment, the majority of the time in your current example would be spent in the foreach option of the template binding. It does quite a bit of work to determine which items in the array were changed to determine how to efficiently add/remove elements from the DOM. In your case, this work is being done 500 times.

You can get better performance, by writing it like:

$("#btnAdd").click(function()
{
    var items = vm.Comments();
    for(var i = 0; i<500; i++) {
         items.push(i.toString());
    }

    vm.Comments.valueHasMutated();
});

This just pushes items to the underlying array without notifying any subscribers until the end (calling push on the observableArray will push the item to the underlying array and call valueHasMutated).

The memory usage on the original sample does seem unusually high. I think that there may be some possible optimizations in the foreach logic that could help, but that would/will take quite a bit more research.

RP is correct. have a look: http://jsfiddle/uLkDP/32/

Another and very similar approach is:

$("#btnAdd").click(function()
{
    var a = ["a", "b"];
    for(var i = 0; i<500; i++)
        a.push(i);

    vm.Comments(a);
});

​ a running example: http://jsfiddle/uLkDP/30/

Oh, One more thing, I used process hacker and monitored the memory usage in Google Chrome. RP approach added roughly 4MB, where the other one added roughly 8M. it does make sense as the second approach uses two arrays.

发布评论

评论列表(0)

  1. 暂无评论