17

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:

  1. How does Javascript stores object?
  2. What is the performance of operations?
  3. Will there ever be any collision or other scenarios which will degrade the performance like in Java

Thanks!

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
user2712937
  • 291
  • 3
  • 11
  • check out this link, it has some good information on your question: https://github.com/benblack86/java-snippets/blob/master/resources/java_collections.pdf – Evan Bechtol Feb 04 '15 at 19:38
  • 1
    @EvanBechtol that paper is about **Java**, and this question is about **JavaScript** performance. – Pointy Feb 04 '15 at 19:39
  • 2
    Object storage is implementation dependent. That said, this question can be answered for v8 and spidermonkey, but these are long answers. – Florian Margaine Feb 04 '15 at 19:39
  • This question is under the Java tag. Regardless, this is a good resource for JS http://javascript.crockford.com/survey.html http://stackoverflow.com/questions/7374171/javascript-big-o-property-access-performance – Evan Bechtol Feb 04 '15 at 19:41
  • 1
    Good question! The answer is, unfortunately, implementation dependent. Basically, all js object handling is O(1). v8 (Chrome's engine) starts off by creating a struct for your object, giving you the fastest possible access. Once a key count is exceeded, it falls back to basically hash-table mode. More on that [here](http://jayconrod.com/posts/52/a-tour-of-v8-object-representation). – Zirak Feb 04 '15 at 19:46
  • Actual for most browsers it's more like LinkedHashMap instead of a HashMap: http://code.google.com/p/v8/issues/detail?id=164 .. what it actual is though is probably more complicated. – Adam Gent Feb 04 '15 at 19:52
  • BTW Java 8 uses a tree for collisions, but these are rare unless you are trying a DOS attack. – Peter Lawrey Feb 04 '15 at 20:17

1 Answers1

10

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):

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.

Community
  • 1
  • 1
ssube
  • 47,010
  • 7
  • 103
  • 140