JS
memory management

and hunting memory leaks

@naugtur, 2024

Who's that guy?

https://naugtur.pl

## JavaScript didn't have leaking problem.

While I introduce you to the topic, checkout this repository:

github.com/naugtur/js-training-examples

Garbage collection


What to collect??

Garbage collection

  1. Copy items that can be reached
  2. Swap
  3. Cleanup is done by not saving the rest
## But all that copying would be expensive
## Generations - Young generation - Nursery (fresh) - Intermediate (1gc old) - Old generation - (2+ gc old) - collected with mark-sweep Major GC - whole heap Minor GC - only young
#### There are many heap spaces now, #### we'll see them soon
            
          young generation         |   old generation
    nursery     |  intermediate    |
                |                  |
   +--------+   |     +--------+   |     +--------+
   | object |---GC--->| object |---GC--->| object |
   +--------+   |     +--------+   |     +--------+
                |                  |
            
          
Details https://github.com/thlorenz/v8-perf/blob/master/gc.md#heap-organization-in-detail
## Some history and credit - Incremental GC (FF16) - Generational GC (FF32) https://hacks.mozilla.org/2014/09/generational-garbage-collection-in-firefox/ - Scheduling GC (Chrome45) - Compacting GC (FF38) https://hacks.mozilla.org/2015/07/compacting-garbage-collection-in-spidermonkey/

Scheduling GC


Smarter garbage collection for smoother browsing and less memory usage, 2015/12/08
V8 garbage collection deep dive

Compacting GC

Compacting Garbage Collection in SpiderMonkey
More compacting GC

Major GC phases

marking -> sweeping -> compacting

## All the complexity in one place: https://github.com/thlorenz/v8-perf/blob/master/gc.md

Maps

used to be called Shpes or Hidden classes

V8 docs Hidden Classes and Inline Caching in V8 (2015)
Shapes and Inline Caches (2018)
Let's look at one picture from the article. image credit https://mathiasbynens.be/notes/shapes-ics

V8 garbage collector (2019)

Orinoko

https://v8.dev/blog/trash-talk
# Freeing memory

How it works

var aBoy = { name: "Johny" },
  aGirl = { name: "Sue" },
  anAnimal = { name: "Garfield" };

aBoy = null;
//Johny can now be garbage-collected
aGirl = { name: "Lucy" };
//Sue can now be garbage-collected

aGirl.ownsAnimal = anAnimal
//we have a new reference to Garfield
anAnimal = null;
//a reference is removed, but it was not the only one
//Garfield can't be garbage-collected
                  

Popular misconceptions

  • no, delete keyword does not free memory
  • seriously, delete just slows you down (creates new Hidden Class)
  • no, setting object to null doesn't remove the object, it changes the reference
## When a reference dies ðŸŠĶ - Reference lifetime (var/let) - Functional scope - Function context is sometimes limited to used references now

Pooling

What if I need thousands of objects for short periods of time? I'm implementing a minigun.

  • Create a set of empty objects you need
  • Make a getter that returns the least recently used one
  • Overwrite its fields with new values
  • Reuse the same N objects without ever causing garbage collection

This really is only useful for things like particle animation or UI rendering libraries

What's the problem?

## What's a leak?
### Leaving a reference to someting you expected to get garbage collected ```js const keptAsLongAsModuleLives = []; module.exports = { doStuff:function(someObject){ keptAsLongAsModuleLives.push(someObject); //do stuff } } ```
## What's not a leak, but could be worse? - unlimited in-memory cache of requests or sessions - asynchronous recursion gone wrong - reading files/uploads into memory instead of streaming - stream with broken backpressure - browser: canvas allocates all pixels on first use `rgba*width*height`
## Tools - heap snapshot + diff view - allocation timeline - force GC - devtools trash icon or --expose-gc - performance.memory (chrome) - process.memoryUsage() (Node.js) [Memory analysis vocabulary](https://developer.chrome.com/docs/devtools/memory-problems/get-started)
## Moar Tools Low level stuff - v8.getHeapSpaceStatistics() (Node.js) - `PerformanceObserver` entryTypes `'gc'` - `%DebugTrackRetainingPath(x)` https://v8.dev/docs/memory-leaks
## How to find a leak
### 😃 - run app - snapshot - run suspect code - snapshot - compare
### 😁 - run app - warm up suspect code - snapshot - benchmark suspect code - snapshot - compare
### ðŸĪŊ - run app - warm up suspect code - snapshot - benchmark suspect code - snapshot - benchmark suspect code - snapshot - compare the two later snapshots
# 🏋ïļ ### Exercise time https://github.com/naugtur/js-training-examples

Forget!

@naugtur
http://naugtur.pl