A toddlers guide to memory leaks in Javascript – Kushan Joshi – Medium


In this article I will take a very simplistic approach in understanding memory leaks and I will also attempt to diagnose them.

In todays world of abundant memory, we seldom worry about memory leakages. But I hate to tell you that we live in a real world and nothing comes for free.

Oh my fancy functional programming

Disclosure: I absolutely love functional programming. Functional programming is cool and with the new ES6 syntax it becomes even cooler.

const arrayAddFirst = (a, b) => [a, ...b];

This example above looks super good. Unless you bro-program with me and I blindly put it inside a heavy duty loop 😎.

result = newData.reduce((p,r) => arrayAddFirst(r, p), []);

Now I don’t want you to judge me for the idiot code above. (virtual hug if you can guess what it does 😁)

for(var i = 0; i < newData.length; i++) { for(var j = 0; j < i; i++) { // stuff here } }

The above code snippet is the old fashion equivalent of our example. Notice how easy it is to see it will run n * (n+1) / 2 times, where n is the length of newData.

The main problem in the example code is that the garbage collector has to kick in frequently. The fancy [a, ...b] array you create every time in the .reduce loop needs to be removed from memory or else it will eventually consume all of the memory.

This example tries to shed light on the important fact that memory is not your best friend. It works in your favour 99% of the time, but when it decides to stab you, it directly stabs you in the eye.

Memory Leaks ….

Generally a javascript application can freeze in two ways:

Infinite loops: You might have accidently written a loop which never terminates.

var x = 0; while(x < 5) { console.log(x); // Warning! do not try this at home  }

Running out of memory: We all know there is limited amount of memory in a computer and if we are not careful we might end up hogging all of the memory.

var x = [ [1] ]; for(var i = 1; i < 100000; i++) { x.push(arrayAddFirst(i, x[i-1])); // Warning! do not try this at home  }

Alright, but what about Memory Leaks??

Ofcourse, you can easily avoid these bad behaviours by being careful. But Memory leaks are one of those nasty devils which silently sit.

Let us define a computer which has infinite resources and let’s call it Deep thought. We will refer to Deep thought in this article DT-42 and you will soon see how we will use DT-42 to figure out memory leaks.

Memory Leaks

A Memory leak in simple terms is forgotten data forever waiting to be used. Let us see an example before we jump to a scientific definition.

function sayHi() { var allNames = []; var emoji = '👋'; return name => { allNames.push(name); return emoji + name; } }

In the example, our program is becoming fatter everytime we call it. The garbage collector is not able to cleanup allNames because the function needs it to push data. It cannot figure out that allNames would never be read and hence it is futile to give it any space in memory.

The Wikipedia says:

memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations[1] in such a way that memory which is no longer needed is not released.

I find it much easier to understand the concept by thinking of it as a symptom. Your program is the patient whose love for memory keeps on increasing without bound.

Most of the time the computer (Garbage Collector) is good enough to spot most of data that you wouldn’t be using anymore and cleans it up for you. But it is not perfect and we are far from having a garbage collector smarter than humans. (If we did have one, it would be writting the code and not us :P)

Give me some real life leakages

The problem with our real life is that we don’t encounter such trivial memory leaks and most often the leakages are lurking behind a seemingly well behaving piece of code (Something as innocent looking as arrayAddFirst). Instead of throwing some real life leakages I would rather show you how to identify a memory leak.

Let us fire Chrome to help diagnose memory leaks.

  1. Open up an empty page.
  2. Open the dev panel (Command+Option+I or Control+Shift+I)
  3. Paste this example code in the console.
function sayHi() { var allNames = []; return name => { allNames.push(name); return '👋 ' + name; } } var hello = sayHi(); hello('Gandhi');

Alright, we have started leaking memory already, now let us open our memory profiler.

You should be able to find it as a memory tab in the dev tools.

For the scope of this article we will focus on Take Heap Snapshot. This functionality takes snapshot of the current memory usage of your program.

In my case it looks something like this:

Great, now we will run our innocent looking function a couple of times.

for(var i=0; i<1000000; i++) { hello('Gandhi'); }

If you take another snapshot, you will see an increased memory usage.

In my case there is a complete difference of 10 megabytes. In a lot of real life cases a jump of several megabytes might be normal and you might want to take multiple snapshots over a span of time to rule out a leak.

You can easily compare two snapshots by clicking on the Summary dropdown and switching to Comparison.

If you compare your new snapshot with the one you took earlier and put #Delta to descending, you will find a huge number in the (string). This is where our memory is leaking. Click on it and you will see a lot of Gandhi‘s.

I really hope this article helped you in understanding memory. This is just one of the several approaches one can take to diagnose a leakage. Please check out the following links for a more advanced take on memory:

If you ❤️ this article, please share this article to spread the words.

Reach out to me on Twitter @kushan2020.

قالب وردپرس