Why will ES6 WeakMap's not be enumerable? - javascript

Before my re-entry in JavaScript (and related) I've done lots of ActionScript 3 and there they had a Dictionary object that had weak keys just like the upcoming WeakMap; but the AS3 version still was enumerable like a regular generic object while the WeakMap specifically has no .keys() or .values().
The AS3 version allowed us to rig some really interesting and usefull constructs but I feel the JS version is somewhat limited. Why is that?
If the Flash VM could do it then what is keeping browsers from doing same? I read how it would be 'non-deterministic' but that is sort of the point right?

Finally found the real answer: http://tc39wiki.calculist.org/es6/weak-map/
A key property of Weak Maps is the inability to enumerate their keys. This is necessary to prevent attackers observing the internal behavior of other systems in the environment which share weakly-mapped objects. Should the number or names of items in the collection be discoverable from the API, even if the values aren't, WeakMap instances might create a side channel where one was previously not available.

It's a tradeoff. If you introduce object <-> object dictionaries that support enumerability, you have two options with relation to garbage collection:
Consider the key entry a strong reference that prevents garbage collection of the object that's being used as a key.
Make it a weak reference that allows its keys to be garbage collected whenever every other reference is gone.
If you do #1 you will make it extremely easy to to shoot yourself in the foot by leaking large objects into memory all over the place. On the other hand, if you go with option #2, your key dictionary becomes dependent on the state of garbage collection in the application, which will inevitably lead to impossible to track down bugs.

Related

How do you destroy keys with Subtle's cryptography API?

In the WebCrypto/Subtle crypto API, you can generate keys and whatnot. However there appears to be a distinct lack of .destroyKey() or something of the sort.
Are keys cleaned up upon their reference count reaching zero or something of the sort? Is there no way to explicitly destroy/remove a key from memory?
Note that my concern isn't one of security as I know this wouldn't give much of a security benefit, though I am worried about resource leaks and the like. It feels weird not being able to clean up after one's self explicitly.
The Web Cryptography Specification writes:
Authors should be aware that this specification places no normative requirements on implementations as to how the underlying cryptographic key material is stored. The only requirement is that key material is not exposed to script, except through the use of the exportKey and wrapKey operations.
This specification places no normative requirements on how implementations handle key material once all references to it go away. That is, conforming user agents are not required to zeroize key material, and it may still be accessible on device storage or device memory, even after all references to the CryptoKey have gone away.
That is, a user agent may chose to discard the key data as soon as its CryptoKey becomes eligible for garbage collection, but may also choose to keep the data around longer, for instance until the entire browsing context is discarded upon navigating to a different page or closing the browser tab.
In practice, the difference is unlikely to matter: You can fit thousands if not millions of keys in the memory of any web-capable device, so exhausting memory due to delayed collection of key material is exceedingly unlikely. And since browser implementers have an incentive to keep memory usage low, most will choose to free key material upon collection of the CryptoKey.

How are arrays implemented in JavaScript? What happened to the good old lists?

JavaScript provides a variety of data structures to be used ranging from simple objects over arrays, sets, maps, the weak variants as well as ArrayBuffers.
Over the half past year I found myself in the spot to recreate some of the more common structures like Dequeues, count maps and mostly different variants of trees.
While looking at the Ecma specification I could not find a description on how arrays implemented on a memory level, supposedly this is up to the underlying engine?
Contrary to languages I am used to, arrays in JavaScript have a variable length, similar to list. Does that mean that elements are not necessarily aligned next to each other in memory? Does a splice push and pop actually result in new allocation if a certain threshold is reached, similar to for example ArrayLists in Java? I am wondering if arrays are the way to go for queues and stacks or if actual list implementations with references to the next element might be suited in JavaScript in some cases (e.g. regarding overhead opposed to the native implementation of arrays?).
If someone has some more in-depth literature, please feel encouraged to link them here.
While looking at the Ecma specification I could not find a description on how arrays implemented on a memory level, supposedly this is up to the underlying engine?
The ECMAScript specification does not specify or require a specific implementation. That is up to the engine that implements the array to decide how best to store the data.
Arrays in the V8 engine have multiple forms based on how the array is being used. A sequential array with no holes that contains only one data type is highly optimized into something similar to an array in C++. But, if it contains mixed types or if it contains holes (blocks of the array with no value - often called a sparse array), it would have an entirely different implementation structure. And, as you can imagine it may be dynamically changed from one implementation type to another if the data in the array changes to make it incompatible with its current optimized form.
Since arrays have indexed, random access, they are not implemented as linked lists internally which don't have an efficient way to do random, indexed access.
Growing an array may require reallocating a larger block of memory and copying the existing array into it. Calling something like .splice() to remove items will have to copy portions of the array down to the lower position.
Whether or not it makes more sense to use your own linked list implementation for a queue instead of an array depends upon a bunch of things. If the queue gets very large, then it may be faster to deal with the individual allocations of a list so avoid having to copy large portions of the queue around in order to manipulate it. If the queue never gets very large, then the overhead of a moving data in an array is small and the extra complication of a linked list and the extra allocations involved in it may not be worth it.
As an extreme example, if you had a very large FIFO queue, it would not be particularly optimal as an array because you'd be adding items at one end and removing items from the other end which would require copying the entire array down to insert or remove an item from the bottom end and if the length changed regularly, the engine would probably regularly have to reallocate too. Whether or not that copying overhead was relevant in your app or not would need to be tested with an actual performance test to see if it was worth doing something about.
But, if your queue was always entirely the same data type and never had any holes in it, then V8 can optimize it to a C++ style block of memory and when calling .splice() on that to remove an item can be highly optimized (using CPU block move instructions) which can be very, very fast. So, you'd really have to test to decide if it was worth trying to further optimize beyond an array.
Here's a very good talk on how V8 stores and optimizes arrays:
Elements Kinds in V8
Here are some other reference articles on the topic:
How do JavaScript arrays work under the hood
V8 array source code
Performance tips in V8
How does V8 optimize large arrays

Javascript Object Big-O

Coming from Java, Javascript object reminds me of HashMap in Java.
Javascript:
var myObject = {
firstName: "Foo",
lastName: "Bar",
email: "foo#bar.com"
};
Java:
HashMap<String, String> myHashMap = new HashMap<String, String>();
myHashMap.put("firstName", "Foo");
myHashMap.put("lastName", "Bar");
myHashMap.put("email", "foo#bar.com");
In Java HashMap, it uses the hashcode() function of the key to determine the bucket location (entries) for storage, and retrieval. Majority of the time, for basic operations such as put() and get(), the performance is constant time, until a hash collision occurs which becomes O(n) for these basic operations because it forms a linked list in order to store the collided entries.
My question is:
How does Javascript stores object?
What is the performance of operations?
Will there ever be any collision or other scenarios which will degrade the performance like in Java
Thanks!
Javascript looks like it stores things in a map, but that's typically not the case. You can access most properties of an object as if they were an index in a map, and assign new properties at runtime, but the backing code is much faster and more complicated than just using a map.
There's nothing requiring VMs not to use a map, but most try to detect the structure of the object and create an efficient in-memory representation for that structure. This can lead to a lot of optimizations (and deopts) while the program is running, and is a very complicated situation.
This blog post, linked in the question comments by #Zirak, has a quite good discussion of the common structures and when VMs may switch from a struct to a map. It can often seem unpredictable, but is largely based on a set of heuristics within the VM and how many different objects it believes it has seen. That is largely related to the properties (and their types) of return values, and tends to be centered around each function (especially constructor functions).
There are a few questions and articles that dig into the details (but are hopefully still understandable without a ton of background):
slow function call in V8 when using the same key for the functions in different objects
Why is getting a member faster than calling hasOwnProperty?
http://mrale.ph/blog/2013/08/14/hidden-classes-vs-jsperf.html (and the rest of this blog)
The performance varies greatly, based on the above. Worst case should be a map access, best case is a direct memory access (perhaps even a deref).
There are a large number of scenarios that can have performance impacts, especially given how the JITter and VM will create and destroy hidden classes at runtime, as they see new variations on an object. Suddenly encountering a new variant of an object that was presumed to be monomorphic before can cause the VM to switch back to a less-optimal representation and stop treating the object as an in-memory struct, but the logic around that is pretty complicated and well-covered in this blog post.
You can help by making sure objects created from the same constructor tend to have very similar structures, and making things as predictable as possible (good for you, maintenance, and the VM). Having known properties for each object, set types for those properties, and creating objects from constructors when you can should let you hit most of the available optimizations and have some awfully quick code.

Closure and garbage collection: most efficient way to remove consecutive nodes from a linked list

I wrote a quick and dirty implementation of a doubly-linked list for javascript. I would like to be able to remove multiple (consecutive) nodes at once, and was wondering: is it enough to just sever the ends of these outer most nodes I am removing, or do I have to remove each node individually. If I understand javascript's garbage collection correctly, once nothing points to those consecutive nodes any more even when they are still connected with each other, they should be taken care of by the garbage collector, is that correct?
If anyone could tell me how I could test or verify this myself, I would highly appreciate that as well.
According to MDN:
As of 2012, all modern browsers ship a mark-and-sweep garbage-collector. All improvements made in the field of JavaScript garbage collection (generational/incremental/concurrent/parallel garbage collection) over the last few years are implementation improvements of this algorithm, but not improvements over the garbage collection algorithm itself nor its reduction of the definition of when "an object is not needed anymore"
Mark and sweep algorithms begin from the root objects and find all reachable objects then collect all the non-reachable ones, so for these browsers severing the nodes will be fine. Older browsers use reference counting, which means objects are only collected once they have 0 references to them, so in this case the cycles of a doubly linked list will be problematic. You would then need to cut the cycles in the consecutive nodes in some way (setting the references to null, delete keyword, so on).
So if you are developing for moden browsers you're all good, but you'll need a slightly more involved solution if you want back compatibility to browsers like IE6/7 (it's always the way, isn't it...)

How can I determine what objects are being collected by the garbage collector?

I have significant garbage collection pauses. I'd like to pinpoint the objects most responsible for this collection before I try to fix the problem. I've looked at the heap snapshot on Chrome, but (correct me if I am wrong) I cannot seem to find any indicator of what is being collected, only what is taking up the most memory. Is there a way to answer this empirically, or am I limited to educated guesses?
In chrome profiles takes two heap snapshots, one before doing action you want to check and one after.
Now click on second snapshot.
On the bottom bar you will see select box with option "summary". Change it to "comparision".
Then in select box next to it select snaphot you want to compare against (it should automaticaly select snapshot1).
As the results you will get table with data you need ie. "New" and "Deleted" objects.
With newer Chrome releases there is a new tool available that is handy for this kind of task:
The "Record Heap Allocations" profiling type. The regular "Heap SnapShot" comparison tool (as explained in Rafał Łużyński answers) cannot give you that kind of information because each time you take a heap snapshot, a GC run is performed, so GCed objects are never part of the snapshots.
However with the "Record Heap Allocations" tool constantly all allocations are being recorded (that's why it may slow down your application a lot when it is recording). If you are experiencing frequent GC runs, this tool can help you identify places in your code where lots of memory is allocated.
In conjunction with the Heap SnapShot comparison you will see that most of the time a lot more memory is allocated between two snapshots, than you can see from the comparison. In extreme cases the comparison will yield no difference at all, whereas the allocation tool will show you lots and lots of allocated memory (which obviously had to be garbage collected in the meantime).
Unfortunately the current version of the tool does not show you where the allocation took place, but it will show you what has been allocated and how it is was retained at the time of the allocation. From the data (and possibly the constructors) you will however be able to identify your objects and thus the place where they are being allocated.
If you're trying to choose between a few likely culprits, you could modify the object definition to attach themselves to the global scope (as list under document or something).
Then this will stop them from being collected. Which may make the program faster (they're not being reclaimed) or slower (because they build up and get checked by the mark-and-sweep every time). So if you see a change in performance, you may have found the problem.
One alternative is to look at how many objects are being created of each type (set up a counter in the constructor). If they're getting collected a lot, they're also being created just as frequently.
Take a look at https://developers.google.com/chrome-developer-tools/docs/heap-profiling
especially Containment View
The Containment view is essentially a "bird's eye view" of your
application's objects structure. It allows you to peek inside function
closures, to observe VM internal objects that together make up your
JavaScript objects, and to understand how much memory your application
uses at a very low level.
The view provides several entry points:
DOMWindow objects — these are objects considered as "global" objects
for JavaScript code; GC roots — actual GC roots used by VM's garbage
collector; Native objects — browser objects that are "pushed" inside
the JavaScript virtual machine to allow automation, e.g. DOM nodes,
CSS rules (see the next section for more details.) Below is the
example of what the Containment view looks like:

Categories

Resources