14

I'm fairly certain I'm having memory leaks using KO version 2.0. I have an observable array that is populated with the result of an AJAX call. This collection is data-bound with a for each to a DIV container. Each object in the array has one single observable value that is bound to a checkbox. I've examined the heap using Chrome and my conclusion is the following:

If the AJAX call returns 3 elements, they are rendered properly on the DOM. If I take a snapshot of the heap at this point, there are three SearchResult objects in there. If I trigger the AJAX call again and it returns 5 elements, all 5 are correctly rendered to the DOM. However, if I take a snapshot of the heap in Chrome, and compare them, there are 8 elements listed as still being on the heap, all of them listed as being "added" and none are listed as "deleted". The DOM display is always correct, but the memory use just keeps climbing and climbing because the old search results are never deallocated.

Can anyone help me or give me pointers for diagnosing the memory leak?

UPDATE

I've created a jsFiddle to show the gist of what I'm doing. I've striped down EVERYTHING but the core functionality and I can still duplicate the memory leak when running on my local machine. Obviously the code won't work as it's posted because it needs to hit my local server to run the search.

UPDATE 2

I pulled the newest 2.1.0.0 Beta version and the leak disappeared. I'm not a huge fan of using beta version of things or of the classic "just upgrade to the new version" fix. I am still very interested in knowing what changed or what I was doing wrong that was creating the leak.

arb
  • 7,753
  • 7
  • 31
  • 66
  • 2
    Does it actually keep going until it runs out of memory? JS engines will not garbage collect things immediately, so what you're seeing could be just the engine not doing the GC as it still has plenty of memory left. – Jani Hartikainen Mar 24 '12 at 18:47
  • I've seen my site using upwards of 450MB. Wouldn't the engine keep using up more and more memory until there wasn't any left to allocate as determined by the OS? Wouldn't that mean that the OS would let the browser continue to use more and more memory until the computer crashes? How would I test to see if it runs out of memory? – arb Mar 24 '12 at 20:28
  • The behavior is hard to predict. You could try having it loop the ajax call time and time again and see if it just keeps using more and more memory. Might help if you try to reduce the code into a small test case which you can put in your question and if it turns out to be a leak, should probably be also sent to KO devs. – Jani Hartikainen Mar 24 '12 at 21:17
  • Are you deleting the originals before making the call to get new ones? – Peter T. LaComb Jr. Mar 27 '12 at 15:21
  • 1
    I'm doing what the Knockout people suggest and setting the array value back to a new blank array, `self.values([])` – arb Mar 27 '12 at 15:36

1 Answers1

11

You're not doing anything wrong, it looks like ko.cleanNode was ignoring foreach bindings and not properly disposing of the outdated objects within the updated observableArray.

https://github.com/SteveSanderson/knockout/issues/271

This has been fixed in 2.1.0beta

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
KodeKreachor
  • 8,852
  • 10
  • 47
  • 64
  • 3
    The [issue you refer to](https://github.com/SteveSanderson/knockout/issues/271) was closed because the reporter was using the Knockout wrong. One should not call applyBindings() more than once on the same DOM node(s). – GregT Jun 13 '12 at 00:55