public
Created

Garbage Collection is a very useful and clever piece of the JavaScript engine. It cleans up pieces of memory that are hanging around for no reason, allowing the machine it is running on to continue running as smoothly as possible without having to move large chunks of memory to and from the hard drive to try to cope. There are times, however, in which you do not want GC to kick in. Where you no longer need a particular object, but you may need a new, "clean" one very shortly. If not handled well, this can result in a lot of new memory being allocated in a short amount of time; memory which needs to be cleaned up by GC. In such instances, however, you may also want things to be performant. The most common case is that of a real-time game, in which you want to create new, similar objects and get rid of them in quick succession. But, if you're not careful, when GC runs it can freeze the page while it works its magic. How do you avoid this? By caching and reusing your objects. This gist is meant as a quick and simple example of how to implement and use such a memory-management method. The code is fully commented with annotations, designed to teach you what exactly is going on here. As it's fairly straightforward to implement, feel free to make your own version for your own code, move things around or remove features you won't be needing. And... Happy coding!

  • Download Gist
reusable Obj class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
// holds all instantiated Obj objects in memory for reuse
var clean = [];
 
function Obj(a, b) {
// reset newObj variable
var newObj = false;
// when function was not called as a "new" contructor...
// (like a "factory" function)
if (!(this instanceof Obj)) {
// ...use newly created object with Obj's prototype
newObj = Object.create(Obj.prototype);
}
// when there are clean objects in memory...
else if (clean.length) {
// ...remove and use last clean object
newObj = clean.pop();
}
 
// when a new object has been found/created...
if (newObj) {
// ...apply arguments to object
Obj.apply(newObj, arguments);
// and return
return newObj;
}
 
// the following will run only when an "this" is an Obj object
// and there were no "clean" objects in memory
this.a = a;
this.b = b;
 
// mark the object as "unclean", or "live"
this.isClean = false;
}
Obj.prototype = {
// this property can be used to tell if the object
// should be considered "live" or "dead", "clean" or "unclean"
// in case the user of this object did not release any references to it
// when the object was .destroy()'d
isClean: true,
 
a: null, b: null,
 
destroy: function () {
// mark the object as "clean" or "dead"
this.isClean = true;
 
this.a = null;
this.b = null;
// add the object to the list of clean objects in memory
clean.push(this);
}
};
 
function log(name, obj) {
console.log(name + " ", obj, "clean.length: " + clean.length);
}
 
// tests
var a = new Obj(1, 2);
a.wasA = true;
log("var a = new Obj(1, 2); a.wasA = true;",a);
var b = new Obj(3, 4);
log("new Obj(3, 4);", b);
a.destroy();
log("a.destory();", a);
var c = new Obj(5, 6);
log("new Obj(5, 6);", c);

Looks like a take on the object pool pattern. Note that it's probably more efficient to just let the GC do its work unless your objects are both:

  • expensive to instantiate (involving network connections, files, or large data chunks, for instance), and
  • need to be instantiated very quickly

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.