2011-06-27 4 views
5

Je laisse Process Explorer ouvert et inspecte la colonne "Private Bytes" du processus firefox.exe. Après avoir appuyé sur le bouton "Ajouter" dans cet exemple:Knockout.js consommant trop de mémoire

<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> 

Avec ce 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()); 
}); 

(voir aussi this jsfiddle)

je fais l'expérience que les octets privés prises par Firefox a augmenté d'environ 50-100 MByte.

Le temps d'exécution est assez long quand je le compare à des implémentations qui ne ont pas suivi des dépendances, étant donné cet exemple:

<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> 

Avec ce 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()); 
}); 

(voir aussi this jsfiddle)

Ma question: Est-ce que les performances sont faibles lors de l'utilisation de Knockout.js ou est-ce que je fais quelque chose de mal?

Répondre

7

En mettant de côté le problème de mémoire, la plupart du temps dans votre exemple actuel sera passé dans l'option foreach de la liaison de modèle. Il fait un peu de travail pour déterminer quels éléments du tableau ont été modifiés pour déterminer comment ajouter/supprimer efficacement des éléments du DOM. Dans votre cas, ce travail est effectué 500 fois.

Vous pouvez obtenir de meilleures performances, en l'écrivant comme:

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

    vm.Comments.valueHasMutated(); 
}); 

Cela pousse simplement les articles au tableau sous-jacent sans en informer les abonnés jusqu'à la fin (appel poussée sur le observableArray poussera l'élément du sous-jacent array et call valueHasMutated).

L'utilisation de la mémoire sur l'échantillon d'origine semble inhabituellement élevée. Je pense qu'il pourrait y avoir des optimisations possibles dans la logique foreach qui pourraient aider, mais cela nécessiterait un peu plus de recherches.

+0

Ceci est une bonne idée, mais n'aide malheureusement pas le problème de mémoire. Beau blog BTW! – kahoon

+0

J'espère pouvoir me pencher là-dessus à un moment donné. Cela aide la mémoire cependant si vous poussez plusieurs articles de la manière que j'ai montrée ci-dessus plutôt qu'un par un. –

0

RP est correct. un coup d'oeil: http://jsfiddle.net/uLkDP/32/

Une autre et une approche très similaire:

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

    vm.Comments(a); 
}); 

un exemple en cours d'exécution: http://jsfiddle.net/uLkDP/30/

Oh, encore une chose, j'ai utilisé hacker processus et a surveillé l'utilisation de la mémoire dans Google Chrome. L'approche RP a ajouté environ 4 Mo, alors que l'autre a ajouté environ 8 Mo. cela a du sens car la seconde approche utilise deux tableaux.