Optimize JavaScript for the V8 Engine

Google's V8 engine has revolutionized the way JavaScript is parsed and read at runtime. Through utilizing things like hidden classes and inline caching, the V8 engine has proven faster than virtually every other engine out there. It powers the world's most popular browser (Chrome) as well as our favorite dev tools like Node.js and MongoDb.

While V8 makes any JavaScript code you write inherently faster, there are still best practices to follow when writing JavaScript specifically for V8. In this article, we discuss the unique characteristics of V8 and how you can optimize your JavaScript code to run on the V8 engine.

Hidden Classes

The V8 engine uses hidden classes to optimize property access time. Traditionally properties are accessed via a dictionary lookup by the JavaScript runtime environment. Since objects can change their type dynamically over time, this is a rather time consuming way to retrieve object properties. V8 solves this issue by creating hidden classes for every unique object at runtime.

This concept is best demonstrated through example. Say you have a Person class with name and age attributes:

function Person(name,age){
  this.name = name;
  this.age = age;
}

var Terry = new Person('Terry', 45);
var Bob = new Person('Bob', 22);

For each property we define in our Person class, V8 creates a hidden class for the object layout. In this particular case, it would create three separate classes (one for the empty Person class, another for the Person class with the name property, and another for a Person with the name and age property). For every property we add to an object, V8 will add a new hidden class to the chain.

This may seem inefficient, but when we create our Terry and Bob instances V8 is able to reference the same hidden class for each object. This greatly improves performance as the engine doesn't have to perform dictionary lookups for each instantiation and can reference the same class in the chain.

Avoid adding properties to objects after creation.

Since V8 creates a new hidden class for every property you add to a given class/object, it's best practice to avoid adding properties to your objects after they've been instantiated. For example:

function Person(name,age){
  this.name = name;
  this.age = age;
}

var Bob = new Person('Bob', 22);

//bad
Bob.gender = "male"

Adding the property gender results in V8 adding another class to the chain. It is better to define the gender property in the Person constructor function to reduce the number of classes added to the chain.

Order matters

Another performance tip involves the order in which you define properties for your class objects. For example:

var Bob = new Person();
var Jane = new Person();
Bob.name = 'Bob';
Bob.age = 22;
//properties defined in different order (age first);
Jane.age = 23;
Jane.name = 'Jane';

This is considered bad practice because Bob and Jane don't define their object properties in the same order. V8 is unable to recognize Bob and Jane as having the same class and will create a separate class in the chain for both instances. Staying consistent and defining the name property first for both instances would be the better solution for V8 optimization.

Inline Caching

Whenever a method is called on a specific object, V8 has to look up the hidden class to determine the offset for selecting a specific property. If V8 recognizes the same hidden class being used, it will bypass the lookup and automatically add the offset to the object pointer. This is called inline-caching and is fundamental to what makes V8 superior performance wise.

Optimize for inline-caching.

To optimize your code for inline-caching, it's better to run the same functions over and over versus running many different functions. By "the same function", we mean functions that take the same argument types and are "monomorphic" in nature. All this really means is that your functions should always accept the same types of arguments (numbers, strings, etc) so V8 can optimize them at runtime with inline-caching. For more information on monomorphic functions and inline-caching, see our article on JavaScript performance tips.

Conclusion

Through it's use of hidden classes and inline-caching, the V8 engine has proven faster and more efficient than other JavaScript runtime environments. By defining properties in constructor functions and staying consistent with object definitions and properties, you can optimize your JavaScript code to play well with V8.

Your thoughts?