Anyhow, If I were to write something like:
var h = 5;
delete h;
...I'd be eliminating the reference, but not the memory.
Now, if I set the variable to null, would that replace the memory with the null object?
var h = 5;
h = null;
If so, wouldn't it be better to not only delete() the reference, but also replace the memory with a null object, for better memory optimization?
var h = 5;
h = null;
delete h;
If I want to create a bucket-load of dynamic objects in a long and complex script, what's the best way to get rid of, or otherwise induce the garbage collector to eliminate, objects? Because in addition to just eliminating references, I had read that you could hint the collector to free memory if it was occupied by null...
There's no destroy. You're probably thinking about delete, but delete can't be used to delete variables, only properties. (Although currently browsers let you get away with it, with varying results.) You can delete global variables by removing them from window, but not locals.
Anyway you don't need to think about this sort of stuff in JavaScript. Set a variable to null and if there are no more variables pointing to the same object, it'll get garbage-collected at some point in the near future. The amount of space taken up by the record of the variable pointing to null is tiny and not worth worrying about. Unless you are making a deliberate closure it'll fall out of scope anyway when the local function exits, becoming eligable for GC.
I had read that you could hint the collector to free memory if it was occupied by null...
Nope. You're just removing the references, the GC will pick up the now orphaned objects and free the memory at its own leisure. You don't get any say in the matter.
Simply drop all references to the buckload and let the garbage collection do the magic.
Related
If I have the following code:
function MyClass() {
this.data = {
// lots of data
};
}
var myClassInstace = new MyClass();
var myobj = {
num:123,
str:"hello",
theClass:myClassInstance
};
I know it's absolutely necessary to do:
myobj.theClass = null;
To free up myClassInstance and its data property for GC. However, what should I do with myobj.num and myobj.str? Do I have to give them a value of null too? Does the fact that they're primitive change anything regarding GC?
The JavaScript runtime that implements garbage collection will be able to collect items as soon as values are no longer reachable from code. This is true for object references as well as primitives. The details of the exact moment the item is collected varies by implementation, but it is not even necessary to set your object references to null (as you state) unless you need the object cleaned up sooner than the natural termination of the current function.
This all ties into the fundamental concept of "scope" and the Scope Chain. When an item is no longer in any other objects scope chain it can be collected. Understanding this clearly will answer this question and also help to understand closures, which are scenarios where items stay in memory longer than you might have expected.
There are a lot of "it depends here", ranging from what your code is doing to what browser you're running in. However, if your object is JIT compiled to not use a map for its attributes, then the number should be an 8 byte double stored inline inside the object. Nulling it will do nothing.
The string and the myclass instance will be a pointer to memory allocated outside the object (since a string can be arbitarily many bytes, it can't be stored inside the object. A compiler could conceivably store one instance of the string in memory and never free it, however). Nulling them can allow the garbage collector to free them before the main object goes out of scope.
However, the real question is why you're worried about this. Unless you have profiled your code and identified garbage collection or memory leaks as a problem, you should not be trying to optimize GC behavior. In particular, unless your myobj object is itself going to be live for a long time, you should not worry about nulling fields. The GC will collect it when it goes out of scope.
setting to undefined (not null) will work however delete is better example delete myobj.theClass
Just to avoid misunderstanding I will say that there is no way to really delete an object from memory in JavaScript. you delete it's references or set them to undefined so that the GC can do it's work and really delete.
this is my code, I do not know if it good for prevent leaking memory ? help and how can I test for leaking memory?
var Test = function () {
this.ar = [];
this.List = function () {
return this.ar;
}
this.Add = function (str) {
this.ar.push(str);
}
}
use:
var t = new Test();
t.Add("One");
t.Add("Two");
t.Add("Three");
alert(JSON.stringify(t.List()));
t = undefined;
alert(JSON.stringify(t.List() ));
Setting t to undefined will clear that reference to the object. If there are no other references to that object in your code, then the garbage collector will indeed free up that Test() object. That's how things work in javascript. You don't delete an object, you just clear any references to it. When all references are gone, the object is available for garbage collection.
The actual delete keyword in javascript is used only to remove a property from an object as in delete t.list.
Different browsers have different tools available for keeping track of memory usage. The most universal, blackbox way I know of for a test is to run a cycle over and over again where you assign very large objects (I often use big strings) into your test (to consume noticable amounts of memory) with some sort of setTimeout() in between some number of runs (to let the garbage collector have some cycles) and then just watch the overall memory usage of the browser. As long as the overall memory usage doesn't keep going up and up as you keep doing more and more runs then you must not have a noticeable leak.
Individual browsers may have more comprehensive measuring tools available. Info here for Chrome.
Say we're writing a browser app where smooth animation is critical. We know garbage collection can block execution long enough to cause a perceptible freeze, so we need to minimize the amount of garbage we create. To minimize garbage, we need to avoid memory allocation while the main animation loop is running.
But that execution path is strewn with loops:
var i = things.length; while (i--) { /* stuff */ }
for (var i = 0, len = things.length; i < len; i++) { /* stuff */ }
And their var statements allocate memory can allocate memory that the garbage collector may remove, which we want to avoid.
So, what is a good strategy for writing loop constructs in JavaScript that avoid allocating memory each one? I'm looking for a general solution, with pros and cons listed.
Here are three ideas I've come up with:
1.) Declare "top-level" vars for index and length; reuse them everywhere
We could declare app.i and app.length at the top, and reuse them again and again:
app.i = things.length; while (app.i--) { /* stuff */ }
for (app.i = 0; app.i < app.length; app.i++) { /* stuff */ }
Pros: Simple enough to implement. Cons: Performance hit by dereferencing the properties might mean a Pyrrhic victory. Might accidentally misuse/clobber properties and cause bugs.
2.) If array length is known, don't loop -- unroll
We might be guaranteed that an array has a certain number of elements. If we do know what the length will be in advance, we could manually unwind the loop in our program:
doSomethingWithThing(things[0]);
doSomethingWithThing(things[1]);
doSomethingWithThing(things[2]);
Pros: Efficient. Cons: Rarely possible in practice. Ugly? Annoying to change?
3.) Leverage closures, via the factory pattern
Write a factory function that returns a 'looper', a function that performs an action on the elements of a collection (a la _.each). The looper keeps private reference to index and length variables in the closure that is created. The looper must reset i and length each time it's called.
function buildLooper() {
var i, length;
return function(collection, functionToPerformOnEach) { /* implement me */ };
}
app.each = buildLooper();
app.each(things, doSomethingWithThing);
Pros: More functional, more idiomatic? Cons: Function calls add overhead. Closure access has shown to be slower than object look-up.
And their var statements allocate memory can allocate memory that the garbage collector may remove, which we want to avoid.
This is slightly misinformed. Simply using var does not allocate memory on the heap. When a function is called, each variable used in the function is allocated in advance on the stack. When the function completes execution, the stack frame is popped and the memory is immediately dereferenced.
Where garbage collection-related memory concerns become a problem is when you're allocating objects on the heap. That means any of the following:
Closures
Event listeners
Arrays
Objects
For the most part, anything where typeof foo returns "function" or "object" (or any of the new ES6 typeof return values) will generate an object on the heap. There's probably more that I can't think of right now.
The thing about objects on the heap is that they can refer to other objects on the heap. So for instance:
var x = {};
x.y = {};
delete x;
In the example above, the browser simply can't deallocate the slot for x, because the value contained within it is of variable size. It lives on the heap, where it could then point to other objects (in this case, the object at x.y). Another possibility is that there's a second reference to the same object:
var x = {};
window.foo = x;
delete x;
The browser simply can't remove the object at x from memory, since something else is still pointed at it.
So long story short, don't worry about removing variables, because they work perfectly well and are totally performant. Heap allocations are the real enemy when it comes to garbage collection, but even a few small heap allocations here and there won't hurt most apps.
In C++ I can define a constructor and destructor explicitly, and then cout << "C or D Called" from with in the constructor/destructor function, to know exactly where.
However in JavaScript how do I know when an object is destructed. The example below is the case that concerns me.
I'm calling an internal function on a timeout and I'm wondering if the object stays alive as long as the timer is running, waiting to call next again.
User Click calls Control
// Calls Control
Control calls Message
var message_object = new Message( response_element );
Message calls Effects
new Effects().fade( this.element, 'down', 4000 );
message_object.display( 'empty' );
Effects
/**
*Effects - build out as needed
* element - holds the element to fade
* direction - determines which way to fade the element
* max_time - length of the fade
*/
var Effects = function( )
{
this.fade = function( element, direction, max_time )
{
element.elapsed = 0;
clearTimeout( element.timeout_id );
function next()
{
element.elapsed += 10;
if ( direction === 'up' )
{
element.style.opacity = element.elapsed / max_time;
}
else if ( direction === 'down' )
{
element.style.opacity = ( max_time - element.elapsed ) / max_time;
}
if ( element.elapsed <= max_time )
{
element.timeout_id = setTimeout( next, 10 );
}
}
next();
}
};
This notion that object destruction is reducible to garbage collection for memory strikes me as dangerously misleading, as the problem isn't reducible to freeing memory.
Destructors are responsible for releasing other resources, such as file descriptors or event listeners, which aren't dealt with automagically by garbage collection. In such cases destructors are absolutely required to unwind state before memory is released, or you will leak resources.
In such cases it's a problem that destructors aren't a first-class notion, whether they need to be called explicitly or can be called implicitly after an object becomes unreachable.
The best way to deal with this is to document your modules appropriately if they need destructors to be used and to underline resource leak scenarios failing such use.
Edit 2020: This answer from #BuffyG is much more accurate and useful than my old answer below. Object destruction is about more than memory leaks, and modern JavaScript has none of the patterns I mentioned.
JS objects don't have destructors per se.
JavaScript objects (and primitives) are garbage collected when they become inaccessible, meaning when there is no possible reference to them in the current execution context. The JavaScript runtime has to continuously monitor for this. So unless you use the delete keyword to remove something, then its destruction is sort of under the hood. Some browsers are bad at detecting references left in closure scope (I'm looking at you, Redmond) and that's why you often see objects being set to null at the end of functions--to make sure that memory is freed in IE.
There is no dynamic memory managment in ECMAscript at all. A Garbage Collector will take care of anything that required memory in your script. So actually the question should be more like,
"How does the Garbage Collector know when it can free memory for objects"
Simply spoken, most GC's look if there are any active references. That might be due to parent context object, prototype chains or any direct access to a given object. In your particular instance, anytime setTimeout gets executed, it'll call next() which closes over the .fade() parent context and the .face() function in turn holds a closure to the Effects function( context ).
That means, as long as there are calls to setTimeout, that whole construct is held in memory.
You can help old'ish GC implementations sometimes a little bit, by nulling variables-/references to it is able to collect some stuff earlier or at all, but modern implementatios are pretty smart about this stuff. You actually don't have to care about things like "Object/Reference live times".
There is an experimental Firefox and Chrome function
window.requestIdleCallback() that calls back when the browser is idle. This could be used to simulate a class instance destructor.
Almost the same effect can be obtained from the following code:
setTimeout(function()
{
// Simulate destructor here
},0);
This sets an automatically-dismissed timeout that completes when the current JavaScript script completes (and the main event loop resumes).
Another important consideration is circular references in data structures: "A refers to B, and B refers to A, and no one anymore refers to either of them." Theoretically this could cause both A and B to be seen as uncollectible, hence a memory-leak.
The topic has been discussed here, with some fairly recent updates:
Is it possible to create a "weak reference" in javascript?
The strategy therein discussed is to "weaken" one of the references between A and B so that the garbage-collector knows it can be broken, thus leading to them eventually being reaped ... or maybe stolen in an out-of-memory situation.
Of course it's also possible to benefit from discipline. If you know you're not going to use something anymore, write a routine that sets its various reference-fields to Null before you abandon it to the garbage collector ... "Be tidy."
Garbage collection strategies in JavaScript have advanced considerably since their earliest implementations since the language has become so important. When you are studying texts on this topic, be sure that they are recent.
I'm currently writing a node.js/socket.io application but the question is general to javascript.
I have an associative array that store a color for each client connection. Consider the following:
var clientColors = new Array();
//This execute each new connection
socket.on('connection', function(client){
clientColors[client.sessionId] = "red";
//This execute each time a client disconnect
client.on('disconnect', function () {
delete clientColors[client.sessionId];
});
});
If I use the delete statement, I fear that it will make a memory leak as the property named after client.sessionId value(associative arrays are objects) won't be deleted, its reference to its value will be gonne but the property will still exist in the object.
Am I right?
delete clientColors[client.sessionId];
This will remove the reference to the object on object clientColors. The v8 garbage collector will pick up any objects with zero references for garbage collection.
Now if you asked whether this created a memory leak in IE4 then that's a different question. v8 on the other hand can handle this easily.
Seeing as you deleted the only reference the property will also be gone. Also note that objects are not "associative arrays" in javascript since ordering is implementation specific and not garantueed by the ES specification.
Since clientColors[client.sessionId] is a primitive value (a string) in this case, it will be cleared immediately.
Let's consider the more complicated case of foo[bar] = o with o being a non-primitive (some object). It's important to understand that o is not stored "inside" foo, but somewhere in an arbitrary memory location. foo merely holds a pointer to that location. When you call delete foo[bar], that pointer is cleared, and it's up to the garbage collector to free the memory taken by o.
BTW: You shouldn't use Array when you want an associative array. The latter is called Object in Javascript and is usually instantiated using the short-hand quasi-literal {}
If you are using the V8 engine or nodejs/io, it may not lead to a leak but it is always advisable to prevent leaks.
Just delete it
delete clientColors[client.sessionId];
Or set it to null
clientColors[client.sessionId] = null;
Which will also cascade to any prototypically inherited objects.
This way there is almost no probability of starting a leak.