How to debug and fix memory leaks in JavaScript

Leak ender

Me harties Pirate Smiley in this post I will give some tips on how you can debug and fix memory leaks in JavaScript. In the end I have also shared a script that can automatically spot too large data structures in any web application.

Finding out you have a problem

A good approach for figuring out if your web application leaks memory is this:

  • Disable all extensions and reload your browser
  • Launch a monitor where you can monitor your browser's memory usage
  • Use your web application extensively

If your web application leaks memory then memory usage will increase linearly (or exponentially if you are really unlucky).

What is leaking memory?

There are three things that can leak memory:

  • 1) you are creating new elements without cleaning unused
  • 2) your browser does not garbage collect correctly
  • 3) you are creating data structures such as functions, objects or lists without cleaning up

I have hit all of these in my JavaScript programming adventures :-)

Solving 1) Are you creating a lot elements?

To solve this is rather simple. After using your application open up a JavaScript console and do:

console.log( document.getElementsByTagName('*').length )

If the number of active elements is increasing as you are using your site then you probably have an issue.

Solving 2) Does the garbage collector collect everything?

This one is really tricky to solve, but luckily for us JavaScript garbage collectors have improved a lot in modern browsers. There are some thing to note:

  • Your can't have active references to dead elements or unused data structures. If you do then they won't be cleaned up by the garbage collector.
  • Circular references should be avoided, even thought it should not be an issue in modern browsers such as IE 8, Chrome, Firefox or Safari. Read more about circular references. And read about memory leak patterns in JavaScript.

If you code with these things in mind then the garbage collector should not be an issue.

To solve garbage collector issues follow the solution for 3) as it's basically the same issue with different causes.

Solving 3) Are you creating data structures without cleaning up?

To spot this you'll need to debug A LOT. But luckily you can code automated tools that can help you detect big data structures. Read more below how I tackled and solved this problem.

War Story: Safari leakage

1) Finding the problem

I found out that Wedoist was leaking memory in Safari. I found this out by re-rendering each view 100 times. After 100 re-renderings the memory usage sky rocketed, here you see memory usage to be 1.3GB:

Memory usage of Wedoist

2) Debugging the problem

Debugging this wasn't easy, but Safari offers excellent developer tools (as most modern browsers do!)

I launched the JavaScript profiler and saw that the call stack got bigger and bigger the more I re-rendered:

Call stack of Safari

At this point I knew that I kept adding event handlers and creating new functions. I debugged this problem by using the JavaScript debugger (by adding some smart breakpoints).

3) Creating a tool that can spot data structure leakage

One of my computer scientist professors once said:

A good computer scientist solves problems. A great computer scientist creates tools that solve problems.

Following this advice I created MemoryLeakChecker that can spot big data structures and can help you debug issues.

Running MemoryLeakChecker on Wedoist yields following list:

Leaking list structure

The bug was easy to fix once I found it and now I have a tool that can help me find such memory issues in the future.

You can download MemoryLeakChecker on github.com

Happy Hacking! Yarrr!! ;-)

Code · Code improvement · Code rewrite · JavaScript · Tips 18. Sep 2010
© Amir Salihefendic. Powered by Skeletonz.