Read the summary of "WeakMap You Didn't Know"

Posted May 27, 20208 min read

Learning materials: https://juejin.im/post/5ecd1ad3e51d45784c52db73

The original text mainly reviewed "JavaScript garbage collection mechanism", "Map/WeakMap difference" and "WeakMap properties and methods". This makes up for the knowledge points that I overlooked.
In addition, we can use the original text to learn Set/WeakSet in the same way, and the effect will be better, which will be introduced later in this article.

To start with a summary, first look at the original outline:
1590506498340-fc46c0dc-545e-433a-bdf3-a1484ad89f21.png

Before starting to introduce WeakMap, first review the garbage collection mechanism in JavaScript, which has a lot to do with the following WeakMap/WeakSet.

  1. Garbage collection mechanism

Here is a brief review of the JavaScript garbage collection mechanism:

Garbage collection(Garbage Collection, abbreviated as GC) is an automatic memory management mechanism. And JavaScript has an automatic garbage collection mechanism.

In JavaScript, data of the original type is allocated to the stack space, and data of the reference type is allocated to the heap space.
\ * \ *

1. Garbage collection in stack space

After the call of the function showName is completed, destroy the showName function by moving down the ESP(Extended Stack Pointer) pointer, and then call other functions, it will overwrite the old memory and store the execution context of another function to achieve garbage collection .
1590500751935-64958788-478d-4530-aace-087b4a81031f.png
Picture from "Browser Working Principles and Practice"

2. Garbage collection in heap space

The basis of the data garbage collection strategy in the heap is:The Generational Hypothesis. which is:

  1. Most objects exist in memory for a very short time, and many objects are quickly inaccessible.
  2. The undead will live longer.

These two features apply not only to JavaScript, but also to most dynamic languages, such as Java and Python.

The V8 engine divides the heap space into two areas:new generation(stores objects with short survival time ) and old generation (stores objects with long survival time), and uses them Different garbage collectors.

  • Deputy garbage collector, mainly responsible for the garbage collection of the new generation.
  • The main garbage collector is mainly responsible for the garbage collection of the old generation.

Regardless of the type of garbage collector, the same garbage collection process is used:Mark active objects and inactive objects, reclaim the memory of inactive objects, and finally organize the memory.
\ * \ *

2.1 Deputy Garbage Collector

Using the Scavenge algorithm to process, the new generation space is divided into two areas, one object area and one free area.
1590501175712-16f72304-e73a-4ac7-8339-e28549182de1.png
Picture from "Browser Working Principles and Practice"

Implementation process:

  • The new object exists in the object area. When the object area is about to be filled, a garbage collection is performed;
  • During the garbage collection process, first mark the garbage in the object area, and then the secondary garbage collector copies and arranges the living objects to the free area in an orderly manner, which is equivalent to completing the memory arrangement.
  • After the copying is completed, the object area and the free area are turned over to complete the garbage collection operation, which also allows the two areas in the new generation to be reused indefinitely.

Of course, there are also some problems:If the data of the copy operation is large, it will affect the cleaning efficiency.

The solution of the JavaScript engine is:set the young generation area to be relatively small, and adopt the object promotion strategy(after two collections of still-lived objects, it will be moved to the old generation area) to avoid the installation of surviving objects due to the small generation area. To fill the entire region.

2.2 Main garbage collector

It is divided into:Mark-Sweep algorithm, and Mark-Compact algorithm.

a) Mark-Sweep algorithm
process:

  • Marking process: Traverse the entire element from a set of root elements, the elements that can be reached are active objects, otherwise they are garbage data;
  • Cleanup process:clean up the marked data and generate a lot of fragmented memory.(Disadvantages:large objects cannot be allocated to sufficient contiguous memory)

![1590501229139-cb26b8c9-faf0-47b6-b049-b1cbf7697edc.png]( https://i0.wp.com/segmentfault.com/img/bVbHGNi "1590501229139-cb26b8c9-faf0-47b6-b049-b1cbf7697"
Picture from "Browser Working Principles and Practice"

b) Mark-Compact algorithm
process:

  • Marking process: Traverse the entire element from a set of root elements, the elements that can be reached are active objects, otherwise they are garbage data;
  • Sorting process:Move all the surviving objects to a section, and then clear the content beyond the end boundary.

1590501238206-2a0eff0e-876a-426d-851e-8f81ee58cbb0.png
Picture from "Browser Working Principles and Practice"

  1. Map VS WeakMap

1. The main difference between Map and WeakMap

The structure of WeakMap is similar to the structure of Map`, and it is also used to generate a set of key-value pairs.
the difference:

  • The key of the Map object can be of any type, but the key in the WeakMap object can only be an object reference(except null);

    const map = new WeakMap();
    map.set(1, 2)
    //TypeError:1 is not an object!
    map.set(Symbol(), 2)
    //TypeError:Invalid value used as weak map key
    map.set(null, 2)
    //TypeError:Invalid value used as weak map key

  • WeakMap cannot contain unreferenced objects, otherwise it will be automatically cleared out of the collection(garbage collection mechanism);

  • The WeakMap object has no size attribute, it is not enumerable, and the size of the collection cannot be obtained.

    const map = new WeakMap();
    const user1 = {name:'leo'};
    const user2 = {name:'pingan'};
    map.set(user1, 'good ~');
    map.set(user2, 'hello');
    map.map(ele => console.log(ele))
    //Uncaught TypeError:map.map is not a function

2.Map disadvantages and WeakMap advantages

  1. Assignment and search operations are O(n) time complexity, because both operations need to traverse the entire array to match.
  2. May cause memory leaks, because the array will always refer to each key and value.

In contrast, WeakMap holds weak references to each key object, which means that garbage collection can be performed correctly when no other references exist. The structure of the native WeakMap is special and effective. The key used for mapping is only valid when it is not recycled.

3. Comparison of Map and WeakMap garbage collection

The larger the amount of data, the more obvious the effect of garbage collection.
Run node --expose-gc weakmap.js from the command line to view the comparison effect.
The --expose-gc parameter indicates that the garbage collection mechanism is allowed to be executed manually.

//weakmap.js
const objNum = 10 * 1024 * 1024;
const useType = 1; //Modify the useType value to test Map and WeakMap
const curType = useType == 1? " Map ":" WeakMap ";
let arr = new Array(objNum);

function usageSize() {
    const used = process.memoryUsage(). heapUsed;
    return Math.round((used/1024/1024) * 100)/100 + "M";
}

if(useType == 1) {
    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    const map = new Map();
    map.set(arr, 1);

    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    arr = null;
    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    console.log("=====")
} else {
    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    const map = new WeakMap();

    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    arr = null;
    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    console.log("=====")
}
  1. Introduction and Application of WeakMap

1. Introduction to WeakMap

The WeakMap object is a collection of key/value pairs, where the keys are weakly referenced.
WeakMap key can only be of type Object.
The original data type cannot be used as a key(such as Symbol).
There are only four methods available in WeakMap:get(),set(),has(),delete().
\ * \ *
For specific properties and methods, please see " MDN WeakMap ".

2.WeakMap application

The original text introduces two application scenarios:"Cache calculation results through WeakMap" and "Keep private data in WeakMap".
There is also a more common scenario:A scenario where DOM nodes are used as keys.

Scene 1:When we want to add data to the DOM, we can use WeakMap.
The advantage is that when the DOM element is removed, the corresponding WeakMap record will also be automatically removed:

const wm = new WeakMap();
const ele = document.getElementById('example');
wm.set(el, 'some information');
wm.get(el) //"some information"

Scene 2:When we want to add event monitoring for DOM elements, we can use WeakMap.

//code 1
ele1.addEventListener('click', handler1, false);
ele2.addEventListener('click', handler2, false);

//code 2
const listener = new WeakMap();

listener.set(ele1, handler1);
listener.set(ele2, handler2);

ele1.addEventListener('click', listener.get(ele1), false);
ele2.addEventListener('click', listener.get(ele2), false);

The advantage of Code 2 compared to Code 1 is:Since the listener function is placed in WeakMap,
Then once the dom objects ele1 and ele2 disappear, the listener functions handler1 and handler2 bound to it will also disappear automatically

  1. Expansion:Set/WeakSet

1. The main difference between Set and WeakSet

The structure of WeakSet is similar to Set`, and it is also a collection of unique values.
the difference:

  • The members of WeakSet can only be objects, not other types of values;

    const ws = new WeakSet();
    ws.add(1)
    //TypeError:Invalid value used in weak set
    ws.add(Symbol())
    //TypeError:invalid value used in weak set

  • The objects in WeakSet are weak references, that is, the garbage collection mechanism does not consider the reference of WeakSet to the object;

  • WeakSet objects do not have a size attribute and are not enumerable, and the size of the collection cannot be obtained.

2. Set/WeakSet garbage collection comparison

Run node --expose-gc weakset.js from the command line to view the comparison effect.

//weakset.js
const objNum = 5000 * 1024;
const useType = 2;
const curType = useType == 1? " Set ":" WeakSet ";
let obj = [];
for(let k = 0; k <objNum; k ++) {
    obj [k]= {}
}

function usageSize() {
    const used = process.memoryUsage(). heapUsed;
    return Math.round((used/1024/1024) * 100)/100 + "M";
}

if(useType == 1) {
    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    const sets = new Set([... obj]);

    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    obj = null;
    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    console.log("=====")
} else {
    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    const sets = new WeakSet(obj);

    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    obj = null;
    global.gc();
    console.log(objNum + 'a' + curType + 'occupied memory:' + usageSize());

    console.log("=====")
}

V. Summary

This article first reviewed the core knowledge points in "WeakMap You Didn't Know", reviewed the "garbage collection mechanism", "Map VS WeakMap" and "WeakMap Introduction and Application", and finally extended the review of "Set/WeakSet" .
In actual business development, it is best to consider the rational use of garbage collection mechanisms, which is also a very common way to improve product performance.