Javascript Objects and Memory Consumption

James Fidler
7Factor Software
5 min readJul 30, 2020

--

A while ago I read an article on different object creation patterns in Javascript. This article described how different patterns could consume more memory than others, and after reading it I wanted to build something to demonstrate what I had learned. I want to learn how to measure memory consumption in the browser, and I wanted to build something that would have a direct effect on my page’s memory consumption so that I could reliably demonstrate the negative effects of poorly written code.

Measuring Memory Usage in Chrome

In the Chrome dev tools, there is a Memory tab. Here you can take a snapshot of the JavaScript VM’s heap and see how much memory is being used by your page. There are more complex options for looking at memory consumption over time which is useful for identifying code that is using a lot of memory, but for this all we need is the Heap snapshot tool.

So, in Chrome, open up the dev tools now and click on the Memory tab:

Heap snapshot should already be selected, so click Take snapshot at the bottom. Medium’s post editor is using 11.5 MB of memory:

Spamming Objects to Consume Memory

To demonstrate some things we need a way to eat memory, so here is our contrived example!

a 10,000-strong square dance

Head on over to https://memorydots.netlify.app/ to see the above in action and to follow along with the examples.

The code spawns a 5x5 square at a random position within the bounds of the canvas, then each dot calls a function every frame that moves it in a random direction. The color of each dot is based on its position which has no relation to the topic at hand; it was just really boring when all the dots were one color.

So What Are We Testing?

We’re going to be creating many dots using different implementations to show how these implementations consume different amounts of memory. So, here is a very simple dot:

There’s not much going on here. The dot generates a starting position, and updatePosition moves it slightly while constraining it to the bounds of the canvas. The code could be simplified, but we’re trying to be wasteful here so let’s put on our cowboy hats and see how much memory these bad boys take up.

Back over to https://memorydots.netlify.app/, if we type 100000 into the Number of Dots text box and hit Create Simple then if your computer is anything like my laptop things will start to get a bit sluggish.

If we take a snapshot of the heap now, we can see how much memory our 100,000 dots are taking up:

13.3 MB. An exorbitant amount of memory. Let’s see if we can leverage the power of inheritance to lower this to a more reasonable amount.

Javascript Prototypes and Inheritance

Behold, the same code in a slightly different shape:

Here we have a function, InheritDot, that when run creates a randomized starting position for itself. It then adds the updatePosition function to its prototype instead of containing it itself. All instances of InheritDot will inherit from the same prototype object, meaning that updatePosition will only exist once regardless of how many dots we make.

Let’s take a look at the memory consumption of 100,000 Inherit Dots. If you’re following along on https://memorydots.netlify.app/, set the count to 100000, click Create Inherit and you should see something like this:

By Grabthar’s Hammer, what a savings! At 7.7 MB we’re using 42% less memory to achieve exactly the same thing.

A side note: We could have improved the Simple Dot by converting updatePosition into a separate module and importing it in like so:

import random from 'lodash.random';
import updatePosition from 'modules/updatePosition';

function SimpleDot(ctx) {
this.x = random(0, ctx.canvas.width);
this.y = random(0, ctx.canvas.height);

this.updatePosition = updatePosition;
}

export default SimpleDot;

It’s still storing a reference to updatePosition for each dot, but at 100,000 dots I was seeing it take memory consumption from the 7.7 MB of the Inherit Dot to 8.1 MB. Much better than 13.3 MB, but it’s worth remembering that even references can take up space.

JavaScript Classes

Controversial to some yet existing regardless, the class keyword brings JavaScript kicking and screaming into the 1960s.

Here is one of our dots implemented in a more Object-Oriented fashion:

We have the class Dot with an update function and a class ClassDot which extends Dot and is only responsible for its initial position. Essentially the same as Inherit Dot, but how does it stack up in memory consumption? On https://memorydots.netlify.app/ make sure the dot count is still 100000 and hit the Create Classbutton:

Identical. When we have a peek under the hood, we can see why:

Both InheritDot and ClassDot have updatePosition in their prototype chain. Classes in JavaScript are a fancy wrapper around regular prototypical inheritance so fundamentally nothing has changed compared to the InheritDot.

Neato!

Yeah! Now you know how to look at memory usage in Chrome, how to write some deliberately wasteful code, and how important it can be to understand what JavaScript is doing under the hood.

The source for the MemoryDots example is available here: https://github.com/terrarum/memorydots

--

--

James Fidler
7Factor Software

am developer, work many hour in code mine to purchase ham burger