Memory Matters: Understanding Heap Snapshots in JavaScript with Chrome devtools

Yaron Galperin
5 min readAug 11, 2024

--

Introduction

As a front-end developer, managing memory effectively is crucial to ensuring performance and stability. One key area where memory management comes into play is the JS heap. Understanding how code interacts with the heap and how the JS engine handles memory allocation can help optimize applications and avoid memory leaks.

What is JavaScript Heap Memory?

The JS heap is a memory used to store objects, functions, and other dynamic data that the code creates during execution. Unlike the call stack, which is used for managing function calls and execution contexts, the heap is responsible for handling the dynamic allocation of memory as objects are created and destroyed.

Note: Heap snapshot and the example in the article is using the code below, feel free to copy this code and run on your browser.

HTML File

Heap Snapshots with Chrome DevTools

Chrome DevTools provides a powerful set of tools for analyzing memory usage. One of these tools is the heap snapshot, which captures the state of the JS heap at a specific point in time that includes JS objects and related DOM nodes on your page.

Capturing a Heap Snapshot

To capture a heap snapshot:

  1. Open DevTools.
  2. Navigate to the “Memory“ tab.
  3. Select “Heap snapshot” (It should be selected by default) and click “Take snapshot” at the bottom.
It should generate this kind of snapshot

But, just a second, what do all those parameters are saying?
How can I read such data?
Let's analyze it together.

Understanding Memory Snapshot Modes

There are several modes to analyze memory snapshots, each providing unique insights into memory usage.
Some of the modes are:

  • Summary — Groups objects by their constructor names. This mode is particularly useful for identifying memory usage patterns and tracking down objects based on their types. For instance, you can see how many instances of a particular object are present and their total memory consumption.
  • Containment — Also known as the Heap Contents view, provides a hierarchical representation of objects. It shows how objects are referenced and retained in memory. This mode is beneficial for analyzing the structure of your objects and understanding the relationships between them.
  • Statistics — View presents a pie chart of memory allocation, showing the relative sizes of different memory parts allocated to code, strings, JS arrays, typed arrays, and system objects. This visual representation helps you quickly understand the distribution of memory usage across different types of objects.

Analyzing the Snapshot (Using ‘Summary’ Mode)

Once We’ve captured a snapshot, we will see a list of objects, constructors, and internal structures that were allocated in memory. Let’s break down couple of constructors:

1. (object shape)

2. Function

  • What It Is: Represents functions and their associated closures.
  • Why It Matters: Functions that capture many variables can retain more memory, which may lead to increased memory usage.

3. (compiled code)

  • What It Is: Refers to JS code that has been compiled by the JS engine V8 for better performance.

Maybe You already asked yourself, what do all the “x numbers“ in grey mean?

They represent the instance counts of objects captured at the time of the snapshot. For example, “×4730” next to “(compiled code)” indicates there are 4,730 instances of compiled code in memory.

Understanding Distance, Shallow Size and Retained Size

Distance, Shallow Size and Retained Size

Three important metrics can give us insights into memory management: Distance, Shallow Size, and Retained Size. Each serves a distinct purpose in helping understand how memory is allocated and retained by different objects in the application.

Distance
  • Distance — measures the number of references (or “hops”) needed to reach an object from a root (global object, window object). It’s useful to determine how deep an object is in the reference graph, which can help in identifying potential memory leaks.
    Distance of 1: The object is directly referenced by a root.
    Distance of 2: The object is referenced by another object that is directly referenced by a root.
    Let’s take our code example and search (cmd + f / ctrl + f) for the word Person as it is a function constructor (watch image above — ‘Distance’). We can see that Person constructor has Distance of 2, because the root in our example is the browser, which it is the window object, having the property person$ , connected to an instance of the Person’s Object.
Shallow Size
  • Shallow Size represents the memory occupied directly by the object itself, which includes the memory needed for the name property. This metric does not account for the memory used by objects that the main object references.
Retained Size
  • Retained Size is a broader measure that includes the memory occupied by the object itself (Shallow Size) plus all objects that would be garbage-collected if this object were deleted. This gives a better sense of how much memory would be freed if a particular object and everything it references were no longer accessible.

Conclusion

Heap snapshots in Chrome DevTools give you a powerful way to keep your app running efficiently by letting you see how memory is used and where leaks might be hiding. Regularly analyzing these snapshots helps you catch issues early, ensuring your app stays fast, smooth, and ready to scale.

Thank you for taking the time to read this article. I hope you enjoyed it.
Happy Coding!

--

--