开发者

How does JavaScript VM implements Object property access? Is it Hashtable?

Objects in JavaScript can be used as Hashtable (the key must be String) Is it perform well as Hashtable the data structure?

I mean , does it implemented as Hashtable behind the scene?

Update: (1) I changed HashMap to hashtable (2) I guess most of the browser implement it the same, if not why not? is there any requirement how to implem开发者_开发问答ent it in the ECMAScript specs?

Update 2 : I understand, I just wonder how V8 and the Firefox JS VM implements the Object.properties getters/setters?


V8 doesn't implement Object properties access as hashtable, it actually implement it in a better way (performance wise)

So how does it work? "V8 does not use dynamic lookup to access properties. Instead, V8 dynamically creates hidden classes behind the scenes" - that make the access to properties almost as fast as accessing properties of C++ objects.

Why? because in fixed class each property can be found on a specific fixed offset location..

So in general accessing property of an object in V8 is faster than Hashtable..

I'm not sure how it works on other VMs

More info can be found here: https://v8.dev/blog/fast-properties

You can also read more regarding Hashtable in JS here:(my blog) http://simplenotions.wordpress.com/2011/07/05/javascript-hashtable/


"I guess most of the browser implement it the same, if not why not? is there any requirement how to implement it in the ECMAScript specs?"

I am no expert, but I can't think of any reason why a language spec would detail exactly how its features must be implemented internally. Such a constraint would have absolutely no purpose, since it does not impact the functioning of the language in any way other than performance.

In fact, this is absolutely correct, and is in fact the implementation-independence of the ECMA-262 spec is specifically described in section 8.6.2 of the spec:

"The descriptions in these tables indicate their behaviour for native ECMAScript objects, unless stated otherwise in this document for particular kinds of native ECMAScript objects. Host objects may support these internal properties with any implementation-dependent behaviour as long as it is consistent with the specific host object restrictions stated in this document"

"Host objects may implement these internal methods in any manner unless specified otherwise;"

The word "hash" appears nowhere in the entire ECMA-262 specification.

(original, continued)

The implementations of JavaScript in, say, Internet Explorer 6.0 and Google Chrome's V8 have almost nothing in common, but (more or less) both conform to the same spec.

If you want to know how a specific JavaScript interpreter does something, you should research that engine specifically.

Hashtables are an efficient way to create cross references. They are not the only way. Some engines may optimize the storage for small sets (for which the overhead of a hashtable may be less efficient) for example.

At the end of the day, all you need to know is, they work. There may be faster ways to create lookup tables of large sets, using ajax, or even in memory. For example see the interesting discussion on this post from John Reseig's blog about using a trie data structure.

But that's neither here nor there. Your choice of whether to use this, or native JS objects, should not be driven by information about how JS implements objects. It should be driven only by performance comparison: how does each method scale. This is information you will get by doing performance tests, not by just knowing something about the JS engine implementation.


Most modern JS engines use pretty similar technique to speed up the object property access. The technique is based on so called hidden classes, or shapes. It's important to understand how this optimization works to write efficient JS code.

JS object looks like a dictionary, so why not use one to store the properties? Hash table has O(1) access complexity, it looks like a good solution. Actually, first JS engines have implemented objects this way. But in static typed languages, like C++ or Java a class instance property access is lightning fast. In such languages a class instance is just a segment of memory, end every property has its own constant offset, so to get the property value we just need to take the instance pointer and add the offset to it. In other words, in compile time an expression like this point.x is just replaced by its address in memory.

May be we can implement some similar technique in JS? But how? Let's look at a simple JS function:

function getX(point) {
  return point.x;
}

How to get the point.x value? The first problem here is that we don't have a class (or shape) which describes the point. But we can calculate one, that is what modern JS engines do. Most of JS objects at runtime have a shape which is bound to the object. The shape describes properties of the object and where these properties values are stored. It's very similar to how a class definition describes the class in C++ or Java. It's a pretty big question, how the Shape of an object is calculated, I won't describe it here. I recommend this article which contains a great explanation of the shapes in general, and this post which explains how the things are implemented in V8. The most important thing you should know about the shapes is that all objects with the same properties which are added in the same order will have the same shape. There are few exceptions, for example if an object has a lot of properties which are frequently changed, or if you delete some of the object properties using delete operator, the object will be switched into dictionary mode and won't have a shape.

Now, let's imagine that the point object has an array of property values, and we have a shape attached to it, which describes where the x value in this property array is stored. But there is another problem - we can pass any object to the function, it's not even necessary that the object has the x property. This problem is solved by the technique called Inline caching. It's pretty simple, when getX() is executed the first time, it remembers the shape of the point and the result of the x lookup. When the function is called second time, it compares the shape of the point with the previous one. If the shape matches no lookup is required, we can take the previous lookup result.

The primary takeaway is that all objects which describe the same thing should have the same shape, i.e. they should have the same set of properties which are added in the same order. It also explains why it's better to always initialize object properties, even if they are undefined by default, here is a great explanation of the problem.

Relative resources:

  • JavaScript engine fundamentals: Shapes and Inline Caches and a YouTube video
  • A tour of V8: object representation
  • Fast properties in V8
  • JavaScript Engines Hidden Classes (and Why You Should Keep Them in Mind)
  • Should I put default values of attributes on the prototype to save space?


this article explains how they are implemented in V8, the engine used by Node.js and most versions of Google Chrome

https://v8.dev/blog/fast-properties

apparently the "tactic" can change over time, depending on the number of properties, going from an array of named values to a dictionary.

v8 also takes the type into account, a number or string will not be treated in the same way as an object (or function, a type of object)

if i understand this correctly a property access frequently, for example in a loop, will be cached.

v8 optimises code on the fly by observing what its actually doing, and how often

v8 will identify the objects with the same set of named properties, added in the same order (like a class constructor would do, or a repetitive bit of JSON, and handle them in the same way.

see the article for more details, then apply at google for a job :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜