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: </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: </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: </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: </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 badges2 Answers
Reset to default 7Setting 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.