Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Garbage-collected cache via Javascript WeakMaps

I want to cache large objects in JavaScript. These objects are retrieved by key, and it makes sense to cache them. But they won't fit in memory all at once, so I want them to be garbage collected if needed - the GC obviously knows better.

It is pretty trivial to make such a cache using WeakReference or WeakValueDictionary found in other languages, but in ES6 we have WeakMap instead, where keys are weak.

So, is it possible to make something like a WeakReference or make garbage-collected caches from WeakMap?

like image 328
wizzard0 Avatar asked Aug 29 '14 11:08

wizzard0


People also ask

How does JavaScript garbage collection work?

The garbage collector takes roots and “marks” (remembers) them. Then it visits and “marks” all references from them. Then it visits marked objects and marks their references. All visited objects are remembered, so as not to visit the same object twice in the future.

What is WeakMap and WeakSet?

WeakMap is Map -like collection that allows only objects as keys and removes them together with associated value once they become inaccessible by other means. WeakSet is Set -like collection that stores only objects and removes them once they become inaccessible by other means.

What is difference between Map and WeakMap?

Differences between Map and WeakMap 1) A WeakMap accepts only objects as keys whereas a Map,in addition to objects, accepts primitive datatype such as strings, numbers etc. 2) WeakMap objects doesn't avert garbage collection if there are no references to the object which is acting like a key.

Why do we use WeakMap?

WeakMaps allows you to store a collection of Key-Value pairs. It adopts the same properties of Map. The Major difference is that keys of WeakMap cannot be a primitive data type. The keys must be of type object and values can be of any data type.


2 Answers

There are two scenarios where it's useful for a hash map to be weak (yours seems to fit the second):

  1. One wishes to attach information to an object with a known identity; if the object ceases to exist, the attached information will become meaningless and should likewise cease to exist. JavaScript supports this scenario.

  2. One wishes to merge references to semantically-identical objects, for the purposes of reducing storage requirements and expediting comparisons. Replacing many references to identical large subtrees, for example, with references to the same subtree can allow order-of-magnitude reductions in memory usage and execution time. Unfortunately JavaScript doesn't support this scenario.

In both cases, references in the table will be kept alive as long as they are useful, and will "naturally" become eligible for collection when they become useless. Unfortunately, rather than implementing separate classes for the two usages defined above, the designers of WeakReference made it so it can kinda-sorta be usable for either, though not terribly well.

In cases where the keys define equality to mean reference identity, WeakHashMap will satisfy the first usage pattern, but the second would be meaningless (code which held a reference to an object that was semantically identical to a stored key would hold a reference to the stored key, and wouldn't need the WeakHashMap to give it one). In cases where keys define some other form of equality, it generally doesn't make sense for a table query to return anything other than a reference to the stored object, but the only way to avoid having the stored reference keep the key alive is to use a WeakHashMap<TKey,WeakReference<TKey>> and have the client retrieve the weak reference, retrieve the key reference stored therein, and check whether it's still valid (it could get collected between the time the WeakHashMap returns the WeakReference and the time the WeakReference itself gets examined).

like image 82
supercat Avatar answered Sep 21 '22 19:09

supercat


is it possible to make WeakReference from WeakMap or make garbage-collected cache from WeakMap ?

AFAIK the answer is "no" to both questions.

like image 40
Soonts Avatar answered Sep 21 '22 19:09

Soonts