javascript memory leak - javascript

i've just noticed that some javascript i;ve just written appears to be leaking memory, it quite a simple piece of code - thanks to jquery - but I can watch it running in taskmanager and the memory usage is slowly clicking up by between 4 and 40 bytes.
All i'm doing is throwing some data at a asp mvc controller/action via getJSON:
$(document).ready(function () {
var olddata = "";
window.setInterval(function () {
var options = JSON.stringify({
orderby: "name"
});
var params = {
options: options,
data: olddata ? JSON.stringify(olddata) : ""
};
$.getJSON("/Home/GetTasks", params, function (json) {
olddata = json;
json = null;
});
params = null;
options = null;
}, 1000);
});
I've bumped up the timer value just to see the problem more readily. I'm obviously doing something wrong here butcan't see what.
Should I be cleaning up the getJSON call?
TIA.

How do you know you're actually leaking memory?
At small numbers like 4 and 40 bytes, you could just be seeing heap growth, but some of the new blocks in the heap are "free" and available for future use so while the overall app memory use grows, the memory isn't actually leaking and will be available for future use so it won't grow forever.
If this is the entire extent of your experiment, then I don't see any issues with the code.
There are three function closures here. The $(document).ready() closure lasts the lifetime of your code, but it's just a one-time deal so there should be no issue.
The anonymous function passed to setInterval() keeps the $(document).ready() closure alive. Each call to the setInterval() anonymous function should be a new call that will get a new set of local variables and release it's old ones when the prior calls runs to completion.
The anonymous function passed to getJSON() creates a closure on the setInterval anonymous function, but that closure should only last until the getJSON function finishes and when it does the setInterval() anonymous function closure should be released.
The only closure that I see that lasts here is the $(document).ready() closure which is something you intend and it's only created once so it should cause no leak.
All the local variables in the getJSON anonymous function are going to be released when the it finishes. The only data from the getJSON call that survives is your assignment of:
olddata = json;
But, each successive assignment is just replacing the data from the previous call so the previous data is no longer referenced and available for recycling by the garbage collector.
There are no DOM manipulations here so there is no opportunity for cross or circular references between DOM and JS.
My conclusion is that I don't see anything that will leak. I see plenty of things using temporary memory so I suspect what you're seeing in the process memory usage is just heap growth, but growth in a way that the memory that has grown will eventually get reused. If the browser is also caching the JSON results, you could be seeing memory cache growth too.
Unfortunately, in today's browsers, it's difficult to tell when it's really a memory leak versus a temporary expansion of browser memory used by caching, general heaps, etc... In the extreme, you could set all caches to be very small and run this for a long time (hundreds of thousands of iterations). If it's not a leak, memory use should eventually flatten out. If it is a leak, memory usage should continue to grow relatively linearly.
Disclaimer: the one disclaimer here is that I'm assuming that the jQuery function $.getJSON() doesn't leak itself and always finishes in a way that cleans up the closure it creates, even if the ajax call is not successful.

Related

How to free memory of previous stack frame in Javascript

I have a number of functions calling the next one in a chain, processing a rather large set of data to an equally large set of different data:
function first_step(input_data, second_step_callback)
{
result = ... // do some processing
second_step_callback(result, third_step);
}
function second_step(intermediate_data, third_step_callback)
{
result = ... // do some processing
third_step_callback(result);
}
function third_step(intermediate_data) { }
first_step(huge_data, second_step);
In third_step I am running out of memory (Chrome seems to kill the tab when memory usage reaches about 1.5 GB).
I think, when reaching third_step(), the input_data from first_step() is still retained, because first_step() is on the call stack, isn't it? At least when the debugger is running, I can see the data.
Obviously I don't need it anymore. In first_step() there is no code after second_step_callback(result, third_step);. Maybe if I could free that memory, my tab might survive processing a data set of this size. Can I do this?
Without seeing a lot more of what you're really doing that is using memory, it's hard for us to tell whether you're just using too much memory or whether you just need to let earlier memory get freed up.
And, memory in Javascript is not "owned" by stack frames so the premise of the question seems to make a bit of a wrong assumption. Memory in Javascript is garbage collected and is eligible for GC when no live, reachable code still has a reference to the data and will get garbage collected the next time the garbage collector gets to run (during JS idle time).
That said, if you have code that makes a succession of nested function calls like your question shows, you can reduce the amount of memory usage, by doing some of these things:
Clear variables that hold large data (just set them to null) that are no longer needed.
Reduce the use of intermediate variables that hold large data.
Reduce the copying of data.
Reduce string manipulations with intermediate results because each one creates block of memory that then has to be reclaimed.
Clear the stack by using setTimeout() to run the next step in the chain and allow the garbage collector a chance to do its thing on earlier temporary variables.
Restructure how you process or store the data to fundamentally use less memory.

DOM: why is this a memory leak?

Consider this quote from the Mozilla Docs on JavaScript memory leaks:
function addHandler() {
var el = document.getElementById('el');
el.onclick = function() {
this.style.backgroundColor = 'red';
}
}
The above code sets up the element to turn red when it is clicked. It
also creates a memory leak. Why? Because the reference to el is
inadvertently caught in the closure created for the anonymous inner
function. This creates a circular reference between a JavaScript
object (the function) and a native object (el).
Please explain the above reasons of leakage in a simple and concise way, I'm not getting the exact point.
Does the site/page face a security problem because of the leakage? How do I avoid them? What other code can cause memory leaks? How can I tell when a memory leak has occurred?
I'm an absolute beginner to the topic of memory leaks. Could someone clarify this stuff for me, step by step?Also can someone help me clarify this statement "This creates a circular reference between a JavaScript object (the function) and a native object (el)."
There are two concepts that will help you understand this example.
1) Closures
The definition of a closure is that Every inner function enjoys access to its parent's function variables and parameters.
When the addHandler() function finishes, the anonymous function still has access to the parent's variable el.
2) Functions = memory
Every time you define a function a new object is created.
What makes this example slightly confusing is that onclick is an event that can only be set to a DOM element once.
So surely el.onclick = function(){}; will just overwrite the old function right?
Wrong! every time addHandler runs, a new function object is created.
In conclusion:
Each time the function runs it will create a new object, with a closure containing el. Seeing as the anonymous function maintains access to el, the garbage collector cannot remove it from memory.
The anon function will maintain access to el, and el has access to the function, that is a circular reference, which causes a memory leak in IE.
Whenever you define a function in JavaScript an execution context is created for it; this execution context contains references to all the variables in the scope chain, starting from the global scope all the way up to the local scope:
function test()
{
var el = document.getElementById('el');
el.onclick = function() {
// execution context of this function: el, test
alert('hello world');
}
}
When test() is done, the anonymous function is not recycled yet because it's now assigned to an element of the DOM; i.e. it's being referenced by a property of the DOM element.
At the same time, the DOM element itself is also part of the function's execution context and now can't be recycled due to the cyclic reference, even though it's not immediately obvious that it's actually used; you can find a demonstration of that in this answer.
That said, nowadays, most JavaScript engines (even those found in IE) use a more advanced garbage collector that can identify unused variables a whole lot better, using techniques such as mark-and-sweep or generational / ephemeral garbage collection.
To make sure you don't run into problems on any browser (though, due to the typical lifespan of a page, this is mostly theoretical):
document.getElementById('el').onclick = function() {
alert('hello world');
}
Also see the more information section of the MS article on the issue:
This memory leak occurs because DOM objects are non-JScript objects.
DOM objects are not in the mark-and-sweep garbage collection scheme of
JScript. Therefore, the circular reference between the DOM objects and
the JScript handlers will not be broken until the browser completely
tears down the page.
but note that in contrast to what is stated in that article (memory will be reclaimed when the browser goes to a new page), this article confirms that a bug in IE 6 caused the memory to be leaked forever.
JavaScript's memory management usually works like this: "as long as it is possible to reach it, keep it". This is basically the paradigm that's behind any garbage collection driven memory model.
Garbage collectors tend to be very good at what they do, they even detect if a certain group of elements is only reachable within this very group of elements. Those groups are also called circular reference, since if you follow the references you'll end up at an element you already visited: you've run a circle.
However, in your example you actually have two objects from two different "worlds":
Internet Explorer uses its own garbage collection scheme for this, separate from the mechanism used by JavaScript. It is the interaction between the two that can cause memory leaks.
And this is exactly what happens and can cause memory leaks.

Javascript application memory handling

i have the below JS:
var z = function(){
return "string";
}
var x = function(){
var y = new z();
var div = document.createElement('div');
div.innerHTML = y;
document.body.appendChild(div);
/*
my code…hundreds of other functions. Entire app is js all data comes through sockets and elements created using JS
*/
}
I have a couple of questions which might sound stupid but I am hoping not.
So inside 'x' is 'y' and 'div'. Now if these 2 elements are only used there do they still 'live' inside the JS on the browser or do they vanish?
Basically do i need to set them to null to avoid any extra memory from being used on useless items.
Also I wrote like 25k of lines using JS and all the elements are created using JS. The app stays up for like 9 hours until they close it and it starts all over again on another day. But for those hours I am worried it will be getting slower due to its size. Could this be true?
In terms of your applications memory usage, every time x() is called it creates a temporary instance of the local variable y. This is discarded once the function has been run to completion.
X is an anonymous function that gives it a new scope . New variables will be inside this scope, also this will become the function object and you can access the global scope with window.
There will be differences in how the various browsers handle this kind of situation but the result is pretty much the same.
Browsers are always being optimised to make them more efficient at handling memory as well as faster. They are optimising scope chain lookup costs away too which should result in improved performance.
Due to nature of your anonymous function x() there may be moments where the browser runs its "garbage collection" which could slow or stop script execution but after that it should run without problems.
The Javascript engines inside the modern browsers can handle incredible processing as many libraries (such as jquery) require large amounts of processing.
I would not worry too much about Javascript engines and your 25k lines, it is more down to your code itself and what it is doing.

Life of JavaScript objects & Memory Leaks

I have researched quite a bit about this but mostly by piecing other questions together, which still leaves some doubt. In an app that does not refresh the browser page at any time and may live for quite a while (hours) without closing (assuming that refreshing a page or navigating to another would restart the js code), what's the best way to ensure objects are released and that there's no memory leak.
These are the specific scenarios I'm concerned about:
All of the code below is within a revealing module pattern.
mycode = function(){}()
variables within functions, I'm sure this one is collected by the GC just fine
function(){ var h = "ss";}
variables within the module, should g = null when it's no longer needed?
var g;
function(){ g = "dd";}
And lastly the life of a jqXHR: is it cleaned up after it returns? Should it be set to null in all cases as a precaution whether kept inside a function or module?
If doing this, is it x cleaned up by the GC after it returns?:
function(){
var x = $.get();
x.done = ...;
x.fail = ...;
}
How about when doing this, will it also be cleaned up after x returns?:
var x;
function(){
x = $.get();
x.done = ...;
x.fail = ...;
}
Lastly, is there a way to cleanup all variables and restart a module without restarting the browser?
variables within functions, I'm sure this one is collected by the GC just fine
Yes.
variables within the module, should g = null when it's no longer needed?
Sure.
And lastly the life of a jqXHR: is it cleaned up after it returns? Should it be set to null in all cases as a precaution whether kept inside a function or module?
Various browsers have had bugs related to XHR that caused the onreadystatechange and anything it closed over to remain uncollectable unless the dev was careful to replace it with a dummy value (xhr.onreadystatechange = new Function('')) but I believe jQuery handles this for you.
Lastly, is there a way to cleanup all variables and restart a module without restarting the browser?
Global state associated with the page will take up browser memory until the page is evicted from the browser history stack. location.replace can help you here by letting you kill the current page and replace it with a new version of the same app without expanding the history stack.
Replace the current document with the one at the provided URL. The difference from the assign() method is that after using replace() the current page will not be saved in session history, meaning the user won't be able to use the Back button to navigate to it.
When you use the word "module", that is not a term that has a well-defined meaning to the browser or its JavaScript interpreter so there is no way to evict a module and only a module from memory. There are several things that you have to worry about that might keep things in memory:
References to JavaScript objects that have been attached to DOM nodes and everything they close over -- event handlers are a very common example.
Live setInterval and setTimeout callbacks and everything they close over.
Properties of the global object and everything they close over.
As you noted, properties of certain host objects like XHR instances, web worker callbacks, etc. and (you guessed it) everything they close over.
Any scheme that is going to unload a module and only a module would need to deal with all of these and figure out which of them are part of the module and which are not. That's a lot of different kinds of cleanup.
Javascript is a garbage-collected language. It relies on the garbage collector to clean up unused memory. So essentially, you have to trust that the GC will do its job.
The GC will (eventually, not necessarily immediately) collect objects that are unreachable to you. If you have a reference to an object, then it is potentially still in use, and so the GC won't touch it.
If you have no reference to the object, directly or indirectly, then the GC knows that the object cannot possibly be used, and the object can be collected. So all you have to do, really, is make sure you reset any references to the object.
However, the GC makes no guarantees about when the object will be collected. And you shouldn't need to worry about that.
Really the only leaks you should worry about are closures.
function foo(a){
var b = 10 + a;
return function(c){
return b + c;
}
}
var bar = foo(20);
var baz = bar(5);
The GC has no way to delete var b - it's out of scope. This is a big problem with IE, not so much with Mozilla and much less with Chrome.
As a rule of thumb with any garbage-collected language (this applies to Java, .NET and JavaScript for example), what you want to do is make sure that there is no lingering reference to a block of memory that you want to have the GC clean up for you. When the GC looks at a block of memory and finds that there is still something in the program referencing it, then it will avoid releasing it.
With regard to the jqXHR, there's no point in you setting them to null at the end of an AJAX function call. All of the parameters of a AJAX success/error/complete will be released once the function returns by the GC unless jQuery is doing something bizarre like keeping a reference to them.
Every variable you can no longer access can be collected by the GC. If you declare a variable inside a function, once the function is quit, the variable can be removed. It is, when the computer runs out of memory, or at any other time.
This becomes more complicated when you execute asynchronous functions like XHR. The done and fail closures can access all variables declared in the outer functions. Thus, as long as done and fail can be executed, all the variables must remain in memory. Once the request is finished, the variables can be released.
Anyway, you should simply make sure that every variable is declared as deep as possible.
Is the first example with 'g', g should be set to null. It will retain the pointer to "dd" otherwise.
In the second example, the 'x' in the first case does not need to be set to null, since that variable will "go away" when the surrounding function exits. In the second case, with 'x' outside of the function, 'x' will retain whatever is assigned to it, and that will not be GC'd until 'x' is set to null or something else.

Does this leak in IE?

I have an aspx page that makes an Ajax request (using jquery) to a web service to return some data.
my onerror handler is something like this (not exactly but this is the idea):
onerror: function(status,xhr, whatever) {
var objectResult = eval('('+xhr.Status+')');
alert(objectResult.Message);
}
Question:
Will this create a potential memory leak due to the eval expression being assigned to my local var?
Thank you.
This will definitely not result in a memory leak.
Your objectResult variable will be destroyed at the end of the function (since it's a local variable).
The actual object in memory that objectResult was referencing is then free to be garbage collected (since the only variable referencing it was destroyed). It probably won't be garbage collected right away, though.
No, this should not create a memory leak. The objectResult variable should be cleaned up as it leaves scope when your handler finishes.

Categories