Initializing variables properly in JavaScript can have significant performance benefits. This can be shown with a simple synthetic benchmark.

notype.js

var x = null;

for (var i = 0; i < 1e8; i++) {
    x = 1 + x;
}

withtype.js

var x = 0;

for (var i = 0; i < 1e8; i++) {
    x = 1 + x;
}

Benchmark Results

$ time node notype.js
node notype.js  **0.30s** user 0.01s system 100% cpu 0.301 total

$ time node withtype.js
node withtype.js  **0.10s** user 0.00s system 99% cpu 0.109 total

This particular benchmark may be trivial, but it demonstrates an important point. In notype.js, x is initialized as null. This makes it impossible for V8 to optimize the arithmetic within the loop, since the type of x must be inferred during the first arithmetic operation. By contrast, the compiler can optimize withtype.js because x is known to be a number.

Running these scripts again with V8’s profiler enabled, we can gain some additional insight into what’s going on under the hood.

notype.js

 [JavaScript]:
   ticks  total  nonlib   name
    181   63.3%   71.8%  LazyCompile: * /home/joseph/dev/jsperf/var_init_value/notype.js:1
     68   23.8%   27.0%  Stub: BinaryOpStub_ADD_Alloc_SMI
      1    0.3%    0.4%  LazyCompile: ~PropertyDescriptor native v8natives.js:482
      1    0.3%    0.4%  KeyedLoadIC: A keyed load IC from the snapshot
      1    0.3%    0.4%  CallInitialize: args_count: 3

withtype.js

 [JavaScript]:
   ticks  total  nonlib   name
     72   66.7%   98.6%  LazyCompile: * /home/joseph/dev/jsperf/var_init_value/withtype.js:1
      1    0.9%    1.4%  LazyCompile: RegExpConstructor native regexp.js:86

The profiler doesn’t give us the full picture here, but we can see that notype.js is spending a fair amount of time in BinaryOpStub_ADD_Alloc_SMI, which V8 uses to create SMI (small integer) values.

It’s possible to dig into this even further by having V8 output the Hydrogen code (the intermediate language which V8 uses to represent the JavaScript code’s abstract syntax tree), or even further by having V8 output the final assembly code. However, both of these things are outside the scope of this post. (If you’re really interested, I’ve posted the output on GitHub.)

If this sort of thing interests you, you might enjoy reading Thorsten Lorenz’s collection of V8 performance resources or Petka Antonov’s V8 optimization killers.

This post was published on 2 August, 2014 and last updated on 1 January, 2017. It was posted in [JavaScript] and tagged with [javascript, performance, v8]