2011-06-27 11 views
5

Utrzymuję otwarty Process Explorer i sprawdzam kolumnę "Private Bytes" procesu firefox.exe. Po naciśnięciu przycisku „Dodaj” w tym przykładzie:Knockout.js zużywa zbyt dużo pamięci

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

Z tym kodem:

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

(patrz również this jsfiddle)

doświadczam, że prywatne bajty podjęte przez Firefox wzrosła o 50-100 MB.

Czas realizacji jest również dość długo, gdy porównać go do implementacji brakuje śledzenia zależności, biorąc pod uwagę ten przykład:

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

Z tym kodem:

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

(patrz również this jsfiddle)

Moje pytanie: Czy słaba wydajność wynika z używania Knockout.js lub czy robię coś nie tak?

Odpowiedz

7

Przez chwilę pomijając problem z pamięcią, większość czasu w bieżącym przykładzie zostanie wydana w opcji wiązania szablonu z foreach. Wykonanie dużej części pracy w celu ustalenia, które elementy tablicy zostały zmienione, pozwala określić sposób efektywnego dodawania/usuwania elementów z modelu DOM. W twoim przypadku ta praca jest wykonywana 500 razy.

można uzyskać lepszą wydajność, pisząc to lubią:

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

    vm.Comments.valueHasMutated(); 
}); 

To tylko popycha przedmiotów do podstawowej tablicy bez powiadamiania żadnych abonentów do końca (wywołanie naciśnięciem na observableArray popchnie element do instrumentu bazowego tablica i wywołanie valueHasMutated).

Wykorzystanie pamięci na oryginalnej próbce wydaje się niezwykle wysokie. Sądzę, że mogą istnieć pewne możliwe optymalizacje w logice, która może pomóc, ale wymagałoby to trochę więcej badań.

+0

To jest miły wgląd, ale niestety nie pomaga problem z pamięcią. Miły blog BTW! – kahoon

+0

Mam nadzieję, że w pewnym momencie zajrzę w to samo. Pomaga jednak pamięci, jeśli przesuniesz wiele elementów w sposób pokazany powyżej, a nie jeden po drugim. –

0

RP jest poprawne. rzucić okiem: http://jsfiddle.net/uLkDP/32/

Kolejnym i bardzo podobne podejście:

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

    vm.Comments(a); 
}); 

uruchomiony przykład: http://jsfiddle.net/uLkDP/30/

Aha, jeszcze jedno, kiedyś proces hakera i monitorować zużycie pamięci w Google Chrome. Podejście RP dodało około 4 MB, a drugie dodało około 8 milionów. ma to sens, ponieważ drugie podejście wykorzystuje dwie tablice.

Powiązane problemy