Sitemap

Array Optimizations in JavaScript Engines

5 min readMar 30, 2018

--

Being a Javascript guy, I’m very much interested in exploring new “good practices” in the Javascript world. Recently, I read about Google’s Javascript V8 engine and I found it awesome how V8 optimizes the code for faster execution. For a web developer, Javascript code plays a very important role in determining the performance of the web application. So, it is very important to understand how JS engines (like Chrome’s V8 engine) work behind the scenes. Javascript in general is a very fast scripting language (thanks to JS engines). JS engines in modern web browsers optimize the code for better performance and faster execution.

There is a property known as “Elements Kinds” which is added by V8 (or any other modern JS engine) to elements in Javascript. Every Elements Kind has a unique code optimization strategy as implemented by the JS engine. Basically, there are two types of arrays internally:

  1. Holey Elements Array (array with holes)
  2. Packed Elements Array (array with no holes)

Javascript engines adapts different approaches for code optimization of these different types of arrays. Performance of Packed Elements Array is better than that of Holey Elements Array.

The diagram here shows some of the most important Elements Kinds in the Javascript engines (there are many others too). Here, in the given diagram, the Upper-Left-most has the best performance and the Lower-Right-most has the worst performance.

A basic diagram explaining the flow of the main Elements Kinds

This diagram will be more clear after going through the example below.

Let’s say we declare an array with three elements. Since, the array elements are declared beforehand as integers, therefore, the V8 engine will add the elements kind as “PACKED_SMI_ELEMENTS” (it is used to store small integer elements in V8 engine). Now, if we push a floating value, the elements kind changes to “PACKED_DOUBLE_ELEMENTS” (it is used to store floating double elements in V8 engine). Again, when we push a string or a character to the array, the elements kind changes to “PACKED_ELEMENTS” (it is used to store all values). So, during this whole phase, the V8 engine adapts to various code optimization techniques due to changes in the Elements Kind (as every Elements Kind has a different code optimization technique). For smaller applications, this decline in performance will not be significant. But for bigger applications, such good practices can produce very much differences in performance.

Now, coming to the Holey Elements Array. When we declare an array in Javascript, the V8 engine allocates some memory space to that array. When the elements are assigned to those memory spaces during declaration, it is termed as a Packed Elements Array; otherwise it is termed as a Holey Elements Array.

Let’s take an example.

Holey Elements Array has lower performance when compared to Packed Elements Array.

The V8 engine has to perform a series of operations in order to execute a statement. In case of Holey Elements, there are more number of steps involved in execution of a line. This results in a declined performance of the Javascript code. For example, for checking the value of array[8], the V8 engine performs several checks before coming to the final conclusion. It follows the series involving the prototype chain for deciding upon the value of array[8]. These steps are necessary in case of Holey elements, and these steps are responsible for poor performance of Holey arrays.

Another important thing in Javascript is that once the Elements Kind changes from PACKED to HOLEY, it can never ever return back to PACKED in its entire life span. For example, here we declare an array of 3 elements. So, the JS engine allocates memory space for 3 elements of the array. Since, these memory spaces have no values, they can be termed as holes (hence, the name HOLEY). After allocation of elements to the array, the array becomes packed, but the Elements Kind will remain “HOLEY_ELEMENTS”. So, the packed array will use the code optimization for HOLEY ARRAYs which will eventually have poor performance as compared to the PACKED ones.

Another great fact about JS is that it treats +0 and -0 differently. Both the values are strictly equal to each other but they have different properties. Basically, they differ in their Elements Kinds.

As we can see below, +0 belongs to the “PACKED_SMI_ELEMENTS” and -0 belongs to the “PACKED_DOUBLE_ELEMENTS”.

Till now, we have discussed about Elements Kinds for arrays but we have not yet discussed about the techniques to use for the best performance. So, for example, we want to declare an array with 9001 elements. What if we do not know the elements of the array? We can follow two approaches:

  1. Declare an array with no elements and don’t give any size during declaration. This will ensure that the array has no holes. Use array.push() operation to insert all 9001 elements. But doing this will lead to another problem. During declaration of array, the V8 engine will allocate some memory to the array, but when the memory will be full after insertion of elements, the V8 engine will again allocate a bigger memory block and shift all the elements to the newer memory block. This shifting operation is very much expensive in terms of performance. In case of 9001 elements, the V8 engine will have to perform this shifting operation multiple times leading to a very poor performance of code execution.
  2. Another approach can be to declare the size of the array beforehand.

But this approach can result to “an array with 9001 holes”. So, here we have a trade-off between the different techniques.

This article gives an insight to the working behind the scenes whenever some Javascript code is executed. This is followed in mostly all modern javascript engines. Mostly all browsers and Node.js uses this approach for code execution and hence as a javascript developer, understanding this helps in writing efficient javascript code.

--

--

Responses (1)