Possible memory leaks in Internet Explorer 7/Backbone? - javascript

I've been playing around with Backbone to see if this framework is a good choice to build on from now on and forward in our application. One requirement is that we must support Internet Explorer 7+ and another is to show at least 200 items per page.
To test the framework I've built a pretty simple list and it works flawlessy in all major browsers except Internet Explorer 7. It seems like there are some memory leaks since each time I reset the data the total rendering time are increased.
I've setup some test scenarios:
With events declared: http://jsfiddle.net/mefraimsson/a2YMF/
Without events declared: http://jsfiddle.net/mefraimsson/u6byQ/
One idea I had was that the events declared never was cleaned up when elements was removed and added to the DOM. When I run the test scenario "without events declared" clicking Reload data frequently the rendering time are pretty stable, but running "With events declared" the rendering time are increased rapidly and the amount of memory used for IE7 is increased. That's why I think that there is some memory leak somewhere.
Are there anyone who have experience with rendering of such large amount of data with Backbone?
Are there anyone who have experienced memory leak problems working with Backbone?
Do you recommend another approach when working with such large amount of data with Backbone? Instead of a large amount of sub-views use one view and iterate over data in template could be a possible solution, but then it feels like you don't get the most out of Backbone?
What is your opinion, do you think it is related to the declaration of events or is it the implemenation of Backbone that's leaking memory?
Thanks in advance

Memory leaks are a common problem in Javascript apps in general. I think there are some frameworks which try to handle this for you, but backbone doesn't. The browser you're using does make some difference in how those leaks are noticed and the problems they cause, but they still exist in other browsers, too. It's generally not the browser that's at fault, but the way event binding is handled in Javascript through the use of callback functions.
I wrote an article discussing this with a suggestion for a way to handle it, specifically with views: http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/
Be sure to read the comments, too. There are some other great suggestions for handling memory leaks in there.

Related

JavaScript: figuring out max memory that could be used in a program

JavaScript in Chrome (or any other browser for that matter, but I rather limit the discussion to Chrome to make it simpler) does not provide an API which can be used to observe memory related information (e.g. how much memory is being used by the current tab where the JS is running).
I am looking for a creative solution for getting an estimation of how much bytes I can cache in a JavaScript object that my web page is running. The problem definition is that I would like to cache as much as possible.
Can anyone think of a decent way of estimating how much memory can a tab handle before it will crash / become unusable on a machine? I guess a statistical approach could work out fine for some cases, but I'm looking for something more dynamic.

How to Identify A Memory Leak with Backbone.js

I believe I have a memory leak in my Backbone.js app. I concluded this after I printed some of my Backbone.View objects to the console, and saw the cid #'s increasing to the hundreds after just a bit clicking around.
Is this increasing cid# a sure sign of a memory leak? Are there any Heap profiling tools I can see the objects that are created, like with Java language? What are the best practices with Backbone.js to ensure no leaks?
Thanks!
The best practice is to use listenTo instead of on and bind. And do not forget to stopListening when you remove an instance.
I would suggest to use Chrome profiler for leaks detection: https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling.
Also you can try to use Chrome plugin for debugging Backbone apps:
https://github.com/Maluen/Backbone-Debugger for debugging Backbone apps.
The profiler is the only source to find out where the leaks are. But there's a much simpler way to see the bigger picture. Go to the timeline then memory in chrome dev tools. It's much easier to read the graph and will show you spikes in memory and DOM creation/destruction.
You shouldn't worry about cleaning leaks until you're app manages the memory as best as possible. Users WILL notice memory spikes because the app will chug; They WON'T notice 99.9% of the leaks.
You're time would be better spend learning how to manage memory in the browser. Backbone doesn't do a good job managing memory. To use memory better: Use object pooling on DOM nodes, update DOM elements when the model changes, keep as much javascript as possible out of the templates, only use the render function once, be careful when loading images. There's a lot of techniques. Here's an example of the techniques to make you're backbone app performant: https://github.com/puppybits/BackboneJS-PerfView.

Javascript clear listeners and variables

I am about to ajaxify my website, but I have observed in some highly ajaxified websites like facebook itself that if you browse for quite some time without refreshing your browser gets slower, respectively more ram is being used and I suppose that is due to javascript "leftovers". It is kind of needless to ask this question if facebook's developers fail to accomplish this but hey, you only lose if you don't try. So the question is "is there a way I can clear variables and listeners from the previous page before loading the new one?". Thank you in advance!
That depends on the browser since each browser does its own Garbage Collection. You can however delete variables and HTML elements and if the GC thinks it can reclaim some memory, it will.
I suggest using some developer tools to actually watch the memory usage in real-time. In Chrome you can create a profile timeline and watch the memory usage grow/shrink. So you can actually see in real-time the effects your code have on memory management.
For testing I like to run cleanup code on a button click so I can know exactly when the code ran and how the memory usage was affected by the code.
And hey, since you're in there playing with dev. tools now, check-out the other tools available to you, they are amazingly helpful.

Best practice: very long running polling processes in Javascript?

I have a touch screen kiosk application that I'm developing that will be deployed on the latest version of Chrome.
The application will need to make AJAX calls to an web service, every 10 minutes or so to pull thru any updated content.
As it's a kiosk application, the page is unlikely to be reloaded very often and theoretically, unless the kiosk is turned off, the application could run for days at a time.
I guess my concern is memory usage and whether or not a very long running setTimeout loop would chew through a large amount of memory is given sufficient time.
I'm currently considering the use of Web Workers and I'm also going to look into Web Sockets but I was wondering if anyone had any experience with this type of thing?
Cheers,
Terry
The browser has a garbage collector so no problems on that. as long as you don't introduce memory leaks through bad code. here's an article and another article about memory leak patterns. that's should get you started on how to program efficiently, and shoot those leaky code.
also, you have to consider the DOM. a person in SO once said that "things that are not on screen should be removed and not just hidden" - this not only removes the entity in a viewing perspective, but actually removes it from the DOM, remove it's handlers, and the memory it used will be freed.
As for the setTimeout, lengthen the interval between calls. Too fast, you will chew up memory fast (and render the page quite... laggy). I just tested code for a timer-based "hashchange" detection, and even on chrome, it does make the page rather slow.
research on the bugs of chrome and keep updated as well.

jQuery or javascript to find memory usage of page

Is there a way to find out how much memory is being used by a web page, or by my jquery application?
Here's my situation:
I'm building a data heavy webapp using a jquery frontend and a restful backend that serves data in JSON. The page is loaded once, and then everything happens via ajax.
The UI provides users with a way to create multiple tabs within the UI, and each tab can contain lots and lots of data. I'm considering limiting the number of tabs they can create, but was thinking it would be nice to only limit them once memory usage has gone above a certain threshold.
Based on the answers, I'd like to make some clarfications:
I'm looking for a runtime solution (not just developer tools), so that my application can determine actions based on memory usage in a user's browser.
Counting DOM elements or document size might be a good estimation, but it could be quite inaccurate since it wouldn't include event binding, data(), plugins, and other in-memory data structures.
2015 Update
Back in 2012 this wasn't possible, if you wanted to support all major browsers in-use. Unfortunately, right now this is still a Chrome only feature (a non-standard extension of window.performance).
window.performance.memory
Browser support: Chrome 6+
2012 Answer
Is there a way to find out how much memory is being used by a web page, or by my jquery application? I'm looking for a runtime solution (not just developer tools), so that my application can determine actions based on memory usage in a user's browser.
The simple but correct answer is no. Not all browsers expose such data to you. And I think you should drop the idea simply because the complexity and inaccuracy of a "handmade" solution may introduce more problem than it solves.
Counting DOM elements or document size might be a good estimation, but it could be quite inaccurate since it wouldn't include event binding, data(), plugins, and other in-memory data structures.
If you really want to stick with your idea you should separate fixed and dynamic content.
Fixed content is not dependant on user actions (memory used by script files, plugins, etc.)
Everything else is considered dynamic and should be your main focus when determining your limit.
But there is no easy way to summarize them. You could implement a tracking system that gathers all these information. All operations should call the appropriate tracking methods. e.g:
Wrap or overwrite jQuery.data method to inform the tracking system about your data allocations.
Wrap html manipulations so that adding or removing content is also tracked (innerHTML.length is the best estimate).
If you keep large in-memory objects they should also be monitored.
As for event binding you should use event delegation and then it could also be considered a somewhat fixed factor.
Another aspect that makes it hard to estimate your memory requirements correctly is that different browsers may allocate memory differently (for Javascript objects and DOM elements).
You can use the Navigation Timing API.
Navigation Timing is a JavaScript API for accurately measuring performance on the web. The API provides a simple way to get accurate and detailed timing statistics—natively—for page navigation and load events.
window.performance.memory gives access to JavaScript memory usage data.
Recommended reading
Measuring page load speed with Navigation Timing
This question is 5 years old, and both javascript and browsers have evolved incredibly in this time. Since this now possible (in at least some browsers), and this question is the first result when you Google "javascript show memory useage", I thought I'd offer a modern solution.
memory-stats.js: https://github.com/paulirish/memory-stats.js/tree/master
This script (which you can run at any time on any page) will display the current memory useage of the page:
var script=document.createElement('script');
script.src='https://rawgit.com/paulirish/memory-stats.js/master/bookmarklet.js';
document.head.appendChild(script);
I don't know of any way that you could actually find out how much memory is being used by the browser, but you might be able to use a heuristic based on the number of elements on the page. Uinsg jQuery, you could do $('*').length and it will give you the count of the number of DOM elements. Honestly, though, it's probably easier just to do some usability testing and come up with a fixed number of tabs to support.
Use the Chrome Heap Snapshot tool
There's also a Firebug tool called MemoryBug but seems it's not very mature yet.
If you want to just see for testing there is a way in Chrome via the developer page to track memory use, but not sure how to do it in javascript directly.
I would like to suggest an entirely different solution from the other answers, namely to observe the speed of your application and once it drops below defined levels either show tips to the user to close tabs, or disable new tabs from opening. A simple class which provides this kind of information is for example https://github.com/mrdoob/stats.js .
Aside of that, it might not be wise for such an intensive application to keep all tabs in memory in the first place. E.g. keeping only the user state (scroll) and loading all the data each time all but the last two tabs are opening might be a safer option.
Lastly, webkit developers have been discussing adding memory information to javascript, but they have gotten in a number of arguments about what and what should not be exposed. Either way, it's not unlikely that this kind of information will be available in a few years (although that information isn't too useful right now).
Perfect question timing with me starting on a similar project!
There is no accurate way of monitoring JS memory usage in-app since it would require higher level privileges. As mentioned in comments, checking the number of all elements etc. would be a waste of time since it ignores bound events etc.
This would be an architecture issue if memory leaks manifest or unused elements persist. Making sure that closed tabs' content is deleted completely without lingering event handlers etc. would be perfect; assuming that it's done you could just simulate heavy usage in a browser and extrapolate the results from memory monitoring (type about:memory in the address bar)
Protip: if you open the same page in IE, FF, Safari... and Chrome; and than navigate to about:memory in Chrome, it will report memory usage across all other browsers. Neat!
What you might want to do is have the server keep track of their bandwidth for that session (how many bytes of data have been sent to them). When they go over the limit, instead of sending data via ajax, the server should send an error code which javascript will use to tell the user they've used too much data.
You can get the document.documentElement.innerHTML and check its length. It would give you the number of bytes used by your web page.
This may not work in all browsers. So you can enclose all your body elements in a giant div and call innerhtml on that div. Something like <body><div id="giantDiv">...</div></body>

Categories

Resources