1

Simple question, what is better for Garbage Collector:

  • adding object to array and assigning null to array cell

this.requests[i] = new NiceClass();

this.requests[i] = null;

  • creating simple variable and assigning null to this variable

var niceClass = new NiceClass();

niceClass = null;

I'm asking because I want to avoid using array, because during creating a lot of object - despite breaking reference to object so garbage collector is able to grab unnecessary objects - array is growing, so I'm curious, is it necessary here or it will be even better to use just variables?

cypherq
  • 13
  • 3
  • depends on the garbage collector. not all GC systems work on reference counting, which is where the `= null` reset stuff comes in somewhat handy. – Marc B Oct 28 '12 at 16:41
  • perhaps this might help: http://stackoverflow.com/questions/1947995/when-should-i-use-delete-vs-setting-elements-to-null-in-javascript – tmslnz Oct 28 '12 at 16:42
  • 3
    I think it's an indication of problematic design when you're spending a lot of time worrying about the garbage collector. – Pointy Oct 28 '12 at 16:45
  • ... also I'm not sure what the effective difference between the two alternatives posted. Storing a reference to an object in an array and storing a reference to an object in a variable; why does it matter? A reference is a reference. – Pointy Oct 28 '12 at 16:49
  • I'm working at job with an large, internet application, with a good architecture but with lot of memory leaks. My task is to optimise everything that is possible to optimise. That's why I'm spending lot of time worrying about GC. – cypherq Oct 28 '12 at 16:51
  • OK well then in my opinion there's absolutely no difference between those two things. What matters is whether there's a live reference to a variable or not; it doesn't matter where the reference is. – Pointy Oct 28 '12 at 16:53
  • yes, but keep in mind, that if I'll store every objects only at variable, I not need array, which is growing, and growing. If I want to add for example 500 objects to this array, is possible that in every loop run, JS engine will create larger array. If I can avoid it, why I shouldn't try? – cypherq Oct 28 '12 at 16:54
  • Then why are you asking at all if already found an acceptable solution for yourself? Go ahead and try it. – Felix Kling Oct 28 '12 at 18:02

1 Answers1

2

A couple of things you're forgetting:

The way JS's GC works depends on the implementation: V8 manages the memory quite good, whereas older versions of IE leaked more than a rusty colander.
Setting a variable to null, however does not initialize it. Null isn't like the null in other languages (just try typing typeof null in your console). Try someVar = undefined instead. Even so, Js does have a reserved delete keyword which seems to me, to be what you're after.
All in all: if the object is referenced by a variable, or an array: it doesn't really matter: arrays are sparse, so if you use delete someArray[i];, there really shouldn't be any difference between that or delete someVar;.
Note: Deleting a variable in the global scope will always return true, but if that variable was explicitly declared (using the var keyword) or if it's a function, it will not be deleted. Only implied globals can be deleted, so:

var global1 = 'I cannot be deleted';
function global2()
{
    global3 = 123;//implied global
}
global4 = function()
{
    console.log('implied global function, can be deleted');
};
delete global1;//returns true
console.log(global1);//I cannot be deleted
delete global2;
global2();//shouldn't create global3, because it was deleted but:
console.log(global3);//123
delete global3;//true
console.log(global3);//undefined, was deleted
delete global4;//true
global4();//error <--- was deleted = reference error

However: in both cases, dereferencing any object that is referenced, still, in a closure somewhere or by another variable somewhere in your script will not GC it.
In General, the JS GC's just flag and swipe the memory in cycles: when all references to any given object go out of scope, they are flagged and the memory is deallocated. You don't have any real control over this process, so you can't really optimize your code for this.

Even so, if you still want to go ahead, and use the timeline and profiler tools in FF or Chrome, then be my guest. But do keep in mind: you're optimizing for a particular JS engine when you're doing that: V8-optimized code might generate cleaner memory in Chrome and Safari, but for all you know, IE might make a complete hash of things, or some of the tricks you've used cause FF to slow down, more than a fairly large array would have done in the first place.
I think I'm going to stop this rant here... Bottom line: You can't optimize something over which you have no real control.

Update:

Since I've just read your comment about the mem-leaks you're currently having: I don't think that setting a variable to null or undefined or even delete-ing it is going to do you much good. A far better way to ensure that (modern) GC's can do their job is clever use of closures: whenever a function returns, the variables that were declared in its scope are marked for GC. if those variables are returned, or the return value of that function is either an object or another function, that reference those variables, they won't be GC'ed, but those variables that are no longer referenced are deallocated.
Global variables never go out of scope and are, therefore, never GC'ed. That's why Globals are evil. If you really have a lot of JS code to optimize: start putting things in IIFE's, that can make a huge difference, with very little effort.

Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • Why would `someVar = undefined` be any different from using `null`? The value returned from `typeof null` doesn't mean much. – I Hate Lazy Oct 28 '12 at 16:54
  • 1
    ...and `delete` is ***not*** for variables. It's only meant for object properties. – I Hate Lazy Oct 28 '12 at 16:55
  • @user1689607: `undefined` is the value that all variables are set too, when the haven't been assigned any value, nut `null`. `typeof null`, in fact returns `object`, just like `typeof []`. using `delete someVar` is the same as doing `delete window.someVar` in the global scope (in case of implied globals, fair enough), so you _are_ delete-ing a property. Anyhow: `someVar= null;` is setting a variable to reference the _null object_, whereas `someVar = undefined` is setting a variable to _no value_, which is marginally more efficient – Elias Van Ootegem Oct 28 '12 at 16:59
  • Yes, `typeof null` returns `"object"`, but that's for historical reasons *(they wanted to fix it for ES6, but backed out because of breakage)*. It's a primitive value like `undefined`, not an object. Using `delete someVar` is certainly not the same as doing `delete window.someVar` in the global, unless you're relying on the presence of IE bugs. – I Hate Lazy Oct 28 '12 at 17:02
  • About `delete` keyword - I agree with user1689607. According to this: http://perfectionkills.com/understanding-delete/ it is not good to use delete; – cypherq Oct 28 '12 at 17:02
  • @cypherq: Yes, I over-simplified. As I said in my comment here: `delete someVar` in the global scope will only work for _implied globals_, not explicitly declared global variables. I'll edit my answer to reflect on that distinction – Elias Van Ootegem Oct 28 '12 at 17:04