2011-06-27 14 views
5

Mantengo Process Explorer abierto e inspecciono la columna "Bytes privados" del proceso firefox.exe. Después de pulsar el botón "Añadir" en este ejemplo:Knockout.js consume demasiada memoria

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

Con este código:

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

(también ver this jsfiddle)

experimento que los bytes privados tomadas por Firefox ha aumentado alrededor 50-100 MByte.

El tiempo de ejecución es también bastante largo cuando lo comparo con implementaciones que carecen de dependencias, teniendo en cuenta este ejemplo:

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

Con este código:

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

(también ver this jsfiddle)

Mi pregunta: ¿El rendimiento es inherente al utilizar Knockout.js o estoy haciendo algo mal?

Respuesta

7

Al dejar de lado la cuestión de la memoria por un momento, la mayoría de las veces en su ejemplo actual se usaría en la opción foreach del enlace de la plantilla. Hace bastante trabajo determinar qué elementos de la matriz se cambiaron para determinar cómo agregar/eliminar elementos de manera eficiente del DOM. En su caso, este trabajo se está haciendo 500 veces.

Usted puede obtener un mejor rendimiento, escribiéndolo como:

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

    vm.Comments.valueHasMutated(); 
}); 

Esto sólo empuja artículos a la matriz subyacente sin notificar a los abonados hasta que el empuje final (pidiendo al observableArray empujará el elemento para el subyacente array y call valueHasMutated).

El uso de memoria en la muestra original parece inusualmente alto. Creo que puede haber algunas optimizaciones posibles en la lógica foreach que podrían ayudar, pero eso requeriría/requerirá un poco más de investigación.

+0

Esta es una buena idea, pero desafortunadamente no ayuda con el problema de memoria. ¡Buen blog por cierto! – kahoon

+0

Espero ver esto yo mismo en algún momento. Sin embargo, ayuda con la memoria si empujas varios elementos de la manera que mostré arriba en lugar de uno por uno. –

0

RP es correcto. echar un vistazo: http://jsfiddle.net/uLkDP/32/

Otra y muy similar enfoque es:

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

    vm.Comments(a); 
}); 

un ejemplo de funcionamiento: http://jsfiddle.net/uLkDP/30/

Ah, una cosa más, he usado hacker de proceso y supervisa el uso de memoria en Google Chrome. El enfoque RP agregó aproximadamente 4MB, donde el otro agregó aproximadamente 8M. tiene sentido ya que el segundo enfoque usa dos matrices.

Cuestiones relacionadas