How to destroy a JavaScript object? - javascript

Recently, I came across one of my application which consumes too much memory and increasing by 10 MB/sec.
So, I like to know how to destroy JavaScript object and variables so memory consumption stays down and my FF can't get destroyed.
I am calling two of my scripts every 8 seconds without reloading the page.
function refresh() {
$('#table_info').remove();
$('#table').hide();
if (refreshTimer) {
clearTimeout(refreshTimer);
refreshTimer = null ;
}
document.getElementById('refresh_topology').disabled=true;
$('<div id="preload_xml"></div>').html('<img src="pic/dataload.gif" alt="loading data" /><h3>Loading Data...</h3>').prependTo($("#td_123"));
$("#topo").hide();
$('#root').remove();
show_topology();
}
How can I see which variable cause Memory overhead, what's the method to stop the execution of that process?

You could put all of your code under one namespace like this:
var namespace = {};
namespace.someClassObj = {};
delete namespace.someClassObj;
Using the delete keyword will delete the reference to the property, but on the low level the JavaScript garbage collector (GC) will get more information about which objects to be reclaimed.
You could also use Chrome Developer Tools to get a memory profile of your app, and which objects in your app are needing to be scaled down.

You can't delete objects, they are removed when there are no more references to them. You can delete references with delete.
However, if you have created circular references in your objects you may have to de-couple some things.

While the existing answers have given solutions to solve the issue and the second half of the question, they do not provide an answer to the self discovery aspect of the first half of the question that is in bold:
"How can I see which variable causes memory overhead...?"
It may not have been as robust 3 years ago, but the Chrome Developer Tools "Profiles" section is now quite powerful and feature rich. The Chrome team has an insightful article on using it and thus also how garbage collection (GC) works in javascript, which is at the core of this question.
Since delete is basically the root of the currently accepted answer by Yochai Akoka, it's important to remember what delete does. It's irrelevant if not combined with the concepts of how GC works in the next two answers: if there's an existing reference to an object it's not cleaned up. The answers are more correct, but probably not as appreciated because they require more thought than just writing 'delete'. Yes, one possible solution may be to use delete, but it won't matter if there's another reference to the memory leak.
Another answer appropriately mentions circular references and the Chrome team documentation can provide much more clarity as well as the tools to verify the cause.
Since delete was mentioned here, it also may be useful to provide the resource Understanding Delete. Although it does not get into any of the actual solution which is really related to javascript's garbage collector.

Structure your code so that all your temporary objects are located inside closures instead of global namespace / global object properties and go out of scope when you've done with them. GC will take care of the rest.

I was facing a problem like this, and had the idea of simply changing the innerHTML of the problematic object's children.
adiv.innerHTML = "<div...> the original html that js uses </div>";
Seems dirty, but it saved my life, as it works!

Related

Experimenting with auto-removed items from WeakSet/WeakMap (via garbage collection) in Node.js when .size doesn't exist?

#1. Workaround for lack of .size property?
In JavaScript, I've never used either WeakSet or WeakMap before, and I don't know that much about garbage collection in general (I'm a PHP + JS developer, so this is the first time I've really needed to think about garbage collection). But I think I have a good use case for WeakMap right now. So I'd like to at least start experimenting with it.
The main thing I want to confirm in my experiments is the automatic removal of objects when they've been garbage collected. This would be easy to test if I could just access a WeakSet.size / WeakMap.size property on the instances to check their size, but they don't exist on the "weak" versions.
If possible, I'm guessing that the results could vary seeing that the size is going to depend on whether the garbage collector has run yet. But that's ok, as none of this experimentation code will be used in production... I just want to confirm that I actually understand how garbage collection and WeakSet/WeakMap are working. The idea of using this feature without being able to test (and therefore fully understand) it makes me very uneasy, and I'm concerned that I'll end up finding out about memory leaks when its too late (in production).
Are there any workarounds or alternatives to deal with the lack of WeakSet.size and WeakMap.size... at least just for debugging/testing/learning purposes?
If not a .size workaround, is there maybe a way to check the memory usage of my WeakMap collection instances? That would be just as useful, as that's where the main concern is.
The only thing I can think of right now is checking the memory of the entire Node.js process... which doesn't seem very reliable to me.
#2. What is .length for?
Also I'm a bit confused about why there is a .length property on the class constructor/instance prototype of both WeakSet and WeakMap (not on your instances of them).
According to:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
...both pages say that .length is:
The value of the length property is 0.
Are they literally just hard-coded to the number 0 at all times? What's the point of that?
Searching for either "WeakSet.length" or "WeakMap.length" on Google (including the double quotes for exact results) yields no further information, only about 20 results for each, which are just mirrors of the MDN pages.
The size won't be available for either WeakSet or WeakMap since their keys are just references to objects, and these are handled by the Garbage Collector. Since the collector cannot be manually controlled (or shouldn't be), it will free the memory of these objects, once they are no longer referenced, at any point during runtime. The workaround you suggest to implement a way to see its current size would not be effective nor recommended considering this.
The length is there since both WeakSet and WeakMap are created through their prototype counterparts. Given how the collector will take care of clearing the object reference at any point,
As for experiment with them, you can try them out in Chrome and expose the garbage collector (and manually calling it) to see how the WeakMap clears itself after an object reference is lost (explained in this answer). Otherwise, you may still see the reference within the WeakMap or WeakSet since devtools usually prevents the garbage collector from running.

What methods are there to prevent the Javascript gc from running as little as possible?

I'm learning Javascript, and in the various texts the authors will speak of javascript using a mark and sweep gc to deallocate objects from memory. They will also speak of how if you set the value a variable references to null it will delete the reference to that value, allowing the allocated space to be set for gc. This SO answer says that you can remove the allocated memory and the reference by setting the value the variable contains to null and then to undefined, effectively removing the allocated space from the heap (if I understood it correctly).
So my question is this: Is it possible to write javascript in such a way that you can eliminate gc?
(If it is implementation specific I would like to know if it is possible on v8, though if this is possible on rhino or other js implementations that would be of immense use too)
Judging by projects like LLJS my request isn't too unreasonable, but I'm not entirely sure how the memory module does it.
I've always found it helpful if I explain why I'm asking so here it goes. I really like compilers, and I wanted to write a compile-to-js language that leveraged a static inferred typing system similar to SML. The reason why I wanted to write my own was because I wanted to utilize region inference to determine exactly when objects and variables come out of scope (as much as possible) and upon leaving scope remove it from the heap, thereby eliminating as much gc as possible. This is mostly a research project (read: because I can) so any resources on memory optimization in javascript would also be greatly appreciated!
EDIT: I guess another way to phrase it would be "Is it possible to write js in such a way that the gc will deterministically never run (as much as possible)? If so what techniques would be involved?"
I'm not looking per se for delete because that marks the element for deletion thereby invoking what I wanted to (try to) avoid, I was curious if the implementation's gc would run if I removed all references (and the value) associated with the variable.
Alternatively, paraphrasing from the referenced SO Answer:
x = foo;
x = null;
x;
Is x still on the heap?
It's not entirely clear what you're looking for.
The standard Javascript implementations have NO way of manually deallocating memory. You can remove a property with the delete operator, but that just removes the property from the object. It doesn't even free any contents that the property points to (that is left for garbage collection if there are no other references to that data).
Javascript was designed from the ground up to be a garbage collected language. It frees things from physical memory only when the garbage collector runs and that garbage collector finds objects that are unreachable (e.g. there are no references to those objects still in use). The language does not contain commands to free memory.
It is possible (in some JS implementations) to call the GC yourself rather than wait for the JS engine to run it, but it's still using GC to decide what to free.
Responding to the additional things you added to your answer.
To the best I know, javascript only cleans things up when the GC runs. Until then objects are marked such that the GC can see that there are no references to them anywhere, but they aren't actually freed until the GC checks and notices this. Further, local variables in a function scope are themselves a type of object and those are not freed until the GC runs and notices that there are no references to the function scope (in JS, a closure can maintain a reference to a function scope even after the function has completed).
So, in your code example:
x = foo; x = null; x;
x is still alive and occupying some space because it's still in scope and code could still reach it. It's contents will be null which presumably takes no extra space beyond the variable itself, but the space for the variable itself won't be freed until the function context it is in is found to be reference free by the garbage collector.
JS is a garbage collected language. That's when things are actually freed from the heap. There are no instructions in the language to free things anytime sooner.
The delete keyword will trigger garbage collection by the browser. Be aware that it deletes entire chains of objects unless you nullify object references.
var o = {...};
delete o;

How to "follow" the references / memory profile of specific Javascript values, or how to tie references in memory profiler to source code

I'd like to know if it's possible (with any browser / dev tools) to pick a specific value or closure variable while debugging and "follow" or "watch" it somehow into future execution points on the page. Basically, a memory profiler attached to just a single value, which would show during debugging or snapshots whether that value is still being retained either directly or indirectly. Alternatively, I'd like to know if it's possible to look at references in the memory profiler/snapshot view in, say, Chrome, and tie those references to actual points in the source code.
My problem is that I am debugging a memory leak caused by rebuilding a DOM tree for a portion of a fairly complex page. Even taking a very controlled memory snapshot that just looks at a single redraw (removing the old DOM tree and adding a new one, where I know that I'm unintentionally retaining a reference to a small part of the old one), there are still hundreds of objects to look through, and to be quite honest I find the memory profiler in Chrome to be very confusing to navigate through. And even when I find references that might be of interest, I'm at a loss as to how to tie them to points in the code - it's great to know that I'm retaining an HTMLDivElement somewhere but that could be almost any of the files...
So basically, I'm unsure how to proceed, and the two solutions I'm asking about are the only things I can think of, if there is any way to do them. Sorry that this is such a vague question, I am open to other ways of tackling this as well.

Count all objects and variables in use

Is it possible to count created objects and variables in javascript?
I am using Google Chrome to analyse my web app. But to debug and find the objects that causes "Memory Leak" is not so easy (at least for me). So I want to know all objects and variables that are created on the current page so I can know if they are removed.
No, you can't do that in Chrome (or any other major browser). You can use Chrome's "memory" page (chrome://memory/) to get some idea what's going on, but it's not down to the object level, and it's important to understand that garbage collection does not happen synchronously or immediately. The browser / JavaScript engine may well allocate memory, use it for some JavaScript objects, and then later correctly understand that those objects aren't used anymore, but keep the memory handy for future use.
Instead, what you can do is study how JavaScript works in detail, which tells you what will (usually) be kept in memory, and why. Understand how closures work (disclosure: that's a post on my anemic little blog), and understand how IE doesn't handle circular references between DOM elements and JavaScript objects well (specifically, it doesn't clean them up well when nothing refers to either of them anymore, which is otherwise not normally a problem). And in general, don't worry too much about it until/unless you have a specific issue to address. (Which absolutely happens, but not as much as people sometimes think.)

Identify javascript closures with developer tools

I am currently developing a website that is pure javascript and relies heavily on the jQuery & jQuery UI libraries (this site is not intended for use by a general public, hence progressive enhancement is not a strict requirement for this project). I am encountering a significant memory leak on executing the following code:
oDialogBox = $("<div>...</div>");
/* Add useful things to the dialog box here */
oDialogBox.appendTo("body");
oDialogBox.dialog({
/* Other dialog box settings here */
close: function(event, ui) {
oDialogBox.dialog("destroy");
oDialogBox.remove();
oDialogBox = null;
}
});
At any given time in this dialog box, I am creating, removing and modifying a large number of instances of jQuery UI buttons, multiselects (per the Multiselect widget created by Eric Hynds) and on click event handlers. According to jQuery UI documentation, calling .remove() on oDialogBox should result in all child widgets being unbound and deleted. Yet my detached DOM tree shows a significant number of garbage elements that the GC isn't collecting.
It is highly likely I have missed a large set of closures that need to be finished off safely. How do I do the following:
1) How do I identify which closures are keeping a given detached DOM object alive (either in Firefox or Chrome)?
2) Assuming the complete set of closures is identified, does anything beyond nulling the variable need to be done to assure marking the DOM element for garbage collection?
3) I have also noticed my list of arrays stored by the page is giant and contains references to DOM elements not being gathered by the GC. Is there a documented best practice for cleaning arrays from javascript and allowing all elements to be marked for deletion? (Note: this is a current prime suspect for the source of the memory leak)
I'm afraid that I don't have a great answer for #1. I haven't found any really good tools for this myself, even given how good the development tools have become over the last few years. The best advice I can give is to always keep things in the smallest scope you possibly can. If things don't escape, it's generally easier to simply figure out where the references must be.
As to #2, there can be further concerns. If the object referenced by variable v1 closes over the free variables of some function, removing v1 will not be enough to make them eligible for garbage collection if another variable v2 closes over v1 in some other function. So I guess if you really mean the "complete set of closures", then you should be all set. But this might get hairy. Again, if most object have references only in narrow scopes, these problems are much less severe.
For #3, what sorts of arrays are you discussing? If it's jQuery collections, then perhaps you simply have too many of them around. The only reason I know for them to stay around for a long time is to bind event handlers to them, and that is almost always better handled by event delegation on parent elements. If it's you're own custom arrays, do you really have a good reason to store references to them in arrays that last for any substantial length of time? I've rarely found one.

Categories

Resources