Private Slots

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Jan 15 15:03:13 PST 2013


On Jan 15, 2013, at 1:58 PM, Brendan Eich wrote:

> The GC cost is one problem, but the property access cost is another, and the second allocation (wm for every obj) yet another. And as Dean just reminded, prototypal inheritance favors symbols. It's not just one cost that motivates symbols over weakmaps if the goal is OO privacy.

Let's consider the just the GC implications  of private symbols versus WeakMaps for a very simple integrity use case -- branding.

Let's assume that we have a class of small, highly ephemeral objects that some important part of a system is very dependent upon. The integrity of the system requires that the instances be well-formed.  Also, these objects are created and discarded at a high rate. (for example, perhaps some kind of Point object that implements some sort of algorithm optimized coordinate encoding). So, we want to "brand" valid instances so that algorithms that consume such objects can ensure that they are dealing with the real thing.

There are, at least, two ways to implement this. One way is to use a WeakMap as a registry for all valid instances of the class.  The other is to use a private Symbol keyed property on each instance as the brand.

Now, before going on we need to understand a few thinks about modern high performance garbage collectors.  One principle that applies to them is that when dealing with very ephemeral objects you want the complexity of the GC algorithms to be proportional to the number of retained (ie, non-garbage) objects processed rather than the number of allocated or garbage objects.  This is because typical application algorithms that use short-lived objects often allocated orders of magnitude more  object than actually remain alive when an GC actually occurs.  This characteristic is foundational to generational GCs.   When it is time to scavenge the nursery, you don't want the GC to have to look at 10s of thousands of allocated Points if only dozens are actually alive at that point in time.  Scavenging ephemeral collectors are fast and low overhead because they only have to inspect or manipulate the actual survivors.  It doesn't matter now many now dead objects were allocated, because the GC doesn't even look at them.

Use of a private Symbol for branding has no impact upon this GC behavior.  The brand is just an object property and if an ephemeral branded object is unreachable it will never be inspected by the GC.

Now consider the impact upon the GC of using WeakMaps for branding.

To start with, WeakMaps uses ephemeron algorithms  that add an extra phase to the GC process and (ignoring other overhead) the cost of this phase will be proportional to the number of allocated branded objects.  You can over simplistically think about it this way: Some WeakDictionary contains an entry for every one of the allocated branded objects.  As a final phase of each GC, each entry in the WeakDictionary must be examined to determine whether it reference an object that was identified as garbage (or conversely, non-garbage) by the previous phases of this GC cycle. If an object was identified as garbage the final phase of the GC cycle must removed it from the dictionary.  So, even though there may only be dozens of surviving branded objects, the GC algorithm may have to explicitly process thousands that are garbage.  You have essentially lost all the advantage of having a generational ephemeral collector.

Ephemeron-based data structures are great for dealing with a moderate number of moderately long-lived objects.  But, if you care about overall system performance you don't want to use them to manage high volumes of very ephemeral  objects.  As someone who has a lot of GC implementation experience I would always choose to use a private Symbol over a WeakMap if either alternative can work for some particular use case.

Allen




More information about the es-discuss mailing list