Managing memory in JavaScript is hard

Managing objects in JavaScript requires an understanding of references and garbage collection. All modern browsers use a method called mark-and-sweep, this means when an object is 'unreachable' it can be cleaned up by the garbage collector. Objects have a constructor for objects in javascript, but there is no clear destructor for objects. The idea behind this blog post is to show you how to allow your objects to be garbage collected in formal and structured way.

Understanding References

To explain references and the Dev Tools I have built this example, if you want the javascript version you can convert it here.

Consider the following: a controller that has a reference to a module (in controller.submodules) and we also store all the modules in a variable called window.modules. The references would look like this:

controller.submodules --> module1 <-- window.modules

Since we have 2 objects referencing module1, if the controller stops referencing module1 then it still stays in memory, because window.modules still has a reference to it.

controller.submodules -x-> module1 <-- window.modules 

Removing the reference to window.modules will remove the last reference to module1 which allows it to get cleaned up by the garbage collector.

controller.submodules -x-> module1 <-x- window.modules 


Taking references into account when building your applications architecture is very important, each module needs to be able to:

  • remove references its holding to any memory
  • notify its parent and anyone else holding the reference that its getting destroyed.
  • The parent and other objects would then remove their references to the child.

Adapting the example from above to hold a reference to a module in 2 controllers, the diagram would change to look like:

firstController.submodules --> module1 <-- secondController.submodules

If pop is called on firstController, the destructor is called and it only removes the reference to the module in firstController.submodules and not secondController.modules. Some architecture decisions have to be made to get this functionality, Backbone.Events provides a good event system to use so we can send destroyed events from the module. The chain of events that happens when the destructor is called:

  • remove references its holding
  • trigger an event on itself to notify anyone holding the reference that its getting destroyed (in this case the controllers).
  • The controllers would then remove its references to the child

Adding Backbone.Events to the above example to clean up references:

Next Step: Object Pooling

Object pooling is simply creating say 10 objects beforehand and then asking the pool for objects instead of creating new ones. When you dont need them anymore, you put them back into the pool. This brings you closer to a static memory footprint, all of these objects are referenced by the pool so you end up flat timeline as opposed to a jagged one.

 (memory timline images from Colt Mcanlis's Performance Checklist for the Mobile Web talk)

This also provides a central authority for managing memory. It becomes more important to have a central authority as you have a more complicated application structure. Taking the example above, How does firstController know its safe to destruct module? What if secondController needs it? There needs to be some sort of central authority.

1. Colt Mcanlis: Performance Checklist for the Mobile Web
2. Delete keyword causes 'slow mode'
3. blog: Object Pooling /w examples
4. Convert CoffeeScript to Javascript

Shane Jonas is a senior engineer at Polar.