Knockout Memory Test Single Page Web App

475 views
Skip to first unread message

Kapil Rakh

unread,
Jul 21, 2012, 4:26:38 PM7/21/12
to knock...@googlegroups.com

Hello,

I am developing a single page web app and I am facing a memory leak issue when using mapping plugin.

With every ajax update I get , the memory goes up and never comes back. I have gone too far to use any other javascript library hence I need your help.

To represent the problem I have created

 

1.       Jsfiddle (http://jsfiddle.net/kapilrakh/UUnwU/8/

In this fiddle, I have tried to simulate the problem by mapping the data again with existing model. Ideally the data would be new with every request ( that is set to happen in 10 seconds interval) .

However everytime I use ko.mapping.fromJS, the memory goes up.

 

2.       Local folder ( see attachment )

In this folder I have an html file and all the js files. This file should be opened with IE as its reading a local file to get the JSON (chrome won’t allow it). All you need to simulate the test is download and unzip the folder , Open html file and click on the link which triggers update cycle.

As with every update, IE memory goes up.

Here is a sieve screenshot.


 

Your help is greatly appreciated. I may have not written an elegant jsfiddle but I hope you understand the problem.

(The object viewModel need to be preserved as I need to let user select a few items and send a different request.)

Please let me know if there is any other approach to better manage memory. The app is supposed to run for days.

Thanks and waiting for the reply. 

Knockout.zip

Kapil Rakh

unread,
Jul 21, 2012, 4:28:10 PM7/21/12
to knock...@googlegroups.com
The sieve shows similar statistics when the local html file is used.

Kapil Rakh

unread,
Jul 22, 2012, 11:15:21 PM7/22/12
to knock...@googlegroups.com
Anyone ?

Paradigm

unread,
Jul 23, 2012, 1:57:43 AM7/23/12
to knock...@googlegroups.com
Have a look at  http://jsfiddle.net/UUnwU/11/  and see if it helps you. You may need to modify your code to suit the example but memory seems to be stable in chrome where before it was forever increasing.

Your show function creates a closure over your viewModel and JavaScript's garbage collection is unsure whether to delete it or not so it keeps it around, essentially creating a duplicate of viewModel every 10 seconds in memory. So in the setInterval function now explicitly removes the closure but you need to make show a method of your viewModel class which could have a major effect depending on how the rest of the code is written. I would try testing the fiddle in IE and then proceeding only if the problem ceases.

szabolc...@gmail.com

unread,
Jul 23, 2012, 2:35:19 AM7/23/12
to knock...@googlegroups.com
I think this may be flawed; by definition you should not be able to delete a variable defined by var (even if you implicitly defined its reference - hence your delete will still return false).

sz

Paradigm

unread,
Jul 23, 2012, 2:39:41 AM7/23/12
to knock...@googlegroups.com, szabolc...@gmail.com
What's the correct route to take for this case then? Setting the variable to null?

szabolc...@gmail.com

unread,
Jul 23, 2012, 3:03:58 AM7/23/12
to knock...@googlegroups.com, szabolc...@gmail.com
I don't know, honestly. If delete "seems to work" for you, use it, but technically it shouldn't (and it returning false indicated it couldn't remove the object). Until all references are destroyed to an object, the GC will not throw it away and knockout does way too much "magic" (especially the automapper) in the background (an even if you manage to clean up references, the gc still is a bitch; just take a look at about:memory).

Right now we're struggling with our single page app like mad, to increase performance and decrease memory usage: it's an uphill battle. Yours:

Szabolcs

Paradigm

unread,
Jul 23, 2012, 3:29:24 AM7/23/12
to knock...@googlegroups.com, szabolc...@gmail.com
Removing the var before vm makes delete return true and the used memory is even lower. This creates a global though so if that delete fails for whatever reason (not that there is a glaring reason why it would fail) you now would have large variables being created in global scope. 

Thanks for letting me know delete doesn't work for those cases, I wasn't aware of its proper usage.

Kapil Rakh

unread,
Jul 23, 2012, 7:30:44 AM7/23/12
to knock...@googlegroups.com, szabolc...@gmail.com
Removing the var keyword before vm didn't help either. Here is updated jsfiddle with that minor change.

Google chrome task manager showed constant increase in memory. The jsfiddle didn't work in IE.
I need to have the viewModel updated rather than deleting and recreating it. (I need that for further processing. e.g. selecting few rows out of them using checkbox and sending it to the server for another operation.)
Thanks for your replies.

Paradigm

unread,
Jul 23, 2012, 8:39:27 AM7/23/12
to knock...@googlegroups.com, szabolc...@gmail.com
http://jsfiddle.net/UUnwU/22/ 

Clearing the interval seems to trigger garbage collection in Chrome at least. I've had it running for 10 minutes and it hasn't surpassed 95,000K which is OK considering jsfiddle is around 50,000K itself.

Just remember to avoid anonymous functions and you'll need to internalise as many as you can across your whole Knockout codebase to see any marked improvement as one stray anonymous function that avoids garbage collection could bring your application to a crawl.

Kapil Rakh

unread,
Jul 23, 2012, 8:51:45 AM7/23/12
to knock...@googlegroups.com
clearInterval(intervalID);    has essentially stopped the 10 seconds update cycle. The call  viewModel.show();  executes only once hence no memory increase.

Paradigm

unread,
Jul 23, 2012, 9:24:35 AM7/23/12
to knock...@googlegroups.com
Of course it does, sorry about that, wasn't thinking properly.

Paradigm

unread,
Jul 23, 2012, 10:01:39 AM7/23/12
to knock...@googlegroups.com
Last try and I'm out.

https://dl.dropbox.com/u/46514/index.html (I don't think jsfiddle is best for measuring memory usage)

Memory usage: hovers around 170,000K even after 60 cycles (10 minutes) but is stable.

There are way too many items on the DOM in this test that the browser becomes laggy when scrolling but I don't think this is a memory issue, more a processing/rendering problem. I'd look into paginating the amount of items on a page at any given time to improve usability. I wouldn't expect 6000 data-bound DOM elements to be responsive using Knockout or any library for that matter.

Another optimisation you could look into is to check your incoming data, compare it to your previously received data, and only re-map the stats attribute if the incoming data is different.

Kapil Rakh

unread,
Jul 23, 2012, 10:52:21 AM7/23/12
to knock...@googlegroups.com
Thanks Paradigm. The performance of the page is great..I am going to focus on the optimisation now..

Roy Jacobs

unread,
Jul 23, 2012, 2:34:32 PM7/23/12
to knock...@googlegroups.com
You've also opened an issue for knockout.mapping discussing this. Is it okay to close it?

Kapil Rakh

unread,
Jul 23, 2012, 3:15:27 PM7/23/12
to knock...@googlegroups.com
Yes. Thanks Roy for the replies.
Reply all
Reply to author
Forward
0 new messages