Does this leak in IE? - javascript

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.

Related

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 declaring variables or not

So this is puzzling to me. Are variables expensive?
Let's take a look at this code:
var div1 = document.createElement('div');
var div2 = document.createElement('div');
div2.appendChild(div1);
Now this one
var div2 = document.createElement('div');
div2.appendChild(document.createElement('div'));
So, on the second example, I'm doing the same thing as on the first one. Is it more expensive to declare a variable than not? Do I save memory by just creating and using an element on the fly?
EDIT: this is a sample code to illustrate the question. I know that in this specific case, the memory saved (or not) in minimal.
Variables are extremely cheap in JavaScript, yet, no matter how cheap they are, everything has a cost.
Having said that, it's not a noticable difference, and you should be thinking more about making your code readable rather than performing micro-optimizations.
You should be using variables to save repeated operations. In your example above, it's likely you need the variable pointing to the newly created div, or you'll be able to do nothing to it... unless you end up retrieving it from the DOM; which will prove many times more costly than the variable, as DOM manipulation is one of the slowest parts of JavaScript.
In theory, there is a tiny little amount of memory you save by not doing the variable declaration, because a variable declaration requires that the JavaScript engine creates a property on the variable binding object for the execution context in which you declare it. (See the specification, Section 10.5 and associated sections.)
In reality, you will never notice the difference, not even on a (relatively) slow engine like IE's. Feel free to use variables wherever they make the code clearer. Creating a property on a variable binding object (e.g., declaring a variable) is a very, very, very quick operation. (Avoid it at global scope, of course, but not because of memory use.)
Caveat: If the variable refers to a big memory structure that you only hold temporarily, and you create closures within that function context, the big memory structure may (in some engines) be kept in memory longer than necesary. Example:
function foo(element) {
var a = /* ...create REALLY BIG structure here */;
element.addEventListener("event", function() {
// Do something **not** referencing `a` and not doing an `eval`
}, false);
}
In an unsophisticated engine, since the event handler is a closure over the context of the call to foo, in theory a is available to the handler and so what it references remains "referencible" and not available for garbage collection until/unless that event handler function is no longer referencible. In any decent engine (like the V8 engine in Chrome), because you neither refer to a nor use eval within the closure (event handler), it's fine. If you want to defend yourself from mediocre engines, set a to undefined before foo returns, so the engine (no matter how mediocre) knows that the event handler won't be referencing that structure even if it were to reference a.
Yes, you save memory, no it is in no way an amount that matters.

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.

javascript memory leak

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.

Memory leak in JavaScript (Chrome)

I'm calling a function 50 times a second, which does some expensive things as it is painting alot on a <canvas> element.
It works great, no problems there, but I just took a look at the memory usage and it was stealing 1MB a second of my RAM. Chrome seems to garbage collect, as it went down each minute or so, but then the usage grew again.
What I tried is putting return at certain places in my function so as to decide what part of my function exactly causes the leak. I've been able to cut it down to a specific line of code, after which the evil part comes, but I don't really know how to solve it.
My questions are:
What tool is available to effectively measure JavaScript memory leaks in Chrome?
Would it be effective to set variables to null / undefined after they have been used, something like disposing them?
If the source code is really necessary I wouldn't hestitate to post it here, but I must admit that it's both long and perhaps a little ununderstandable for others.
I'm just going to pull this quote directly, linked from the article;
Speaking of memory leaks, breaking circular references — the cause of the leaks — is usually done with simple null assignment. There’s usually no need to use delete. Moreover, null‘ing allows to “dereference” variables — what delete would normally not be able to do.
var el = document.getElementById('foo');
// circular reference is formed
el.onclick = function() { /* ... */ };
// circular reference is broken
el = null;
// can't `delete el` in this case, as `el` has DontDelete
For these reasons, it’s best to stick with null‘ing when breaking circular references.
delete Explained
Look at heap profile under the Profiles tab in Chrome's developer tools for information about memory usage.
You can do the following to prevent memory leaks:
Test your code with JSLint, to see if that will give you some pointers.
Use the var keyword to give your variables function scope, so they can be garbage collected when they go out of scope. Without the var keyword variables have global scope.
Use delete variable; statements to remove the object as well as the reference from memory. Setting the variable to null will only remove the object from memory, but not its reference.

Categories