Optimizing Javascript

Michael Stanton

  • Google V8: Compiler Team/Manager
  • V8: ICs and Feedback Vectors
  • Cats, climbing and old typewriters :p

V8 Team, based in Munich

  • ~25 people
  • A few in San Francisco and London

We work on Chromium

  • Open source
  • Branded also as "Chrome"
  • Chromium is huge - we only know a part!

V8 has many features

  • "Hidden Classes"
  • ICs (Inline caches) - how we learn
  • Generational Garbage Collector
  • Pipelined Architecture

Compilation pipeline with learning

Source
Code

Ignition

Byte
Code

Run for a while

Gather feedback

Google proprietary

Compilation pipeline with learning

Source
Code

Ignition

Turbofan

Byte
Code

Optimized
Code

Google proprietary

Compilation pipeline with learning

Source
Code

Ignition

Turbofan

Byte
Code

Optimized
Code

Deoptimization

Google proprietary

TurboFan

  • The "Last Step" in the Pipeline
  • Inlining
  • Allocation Folding
  • Escape Analysis
  • Load Elimination
  • Write Barrier Elimination
  • etc!

Inlining

function bar(a) { 
  return a + 3; 
}

function foo(x) { 
  return bar(5) + x; 
}

Inlining "bar" into "foo"

function bar(a) { 
  return a + 3; 
}

function foo(x) { 
  return 5 + 3 + x; 
}

Inlining "bar" into "foo"

function bar(a) { 
  return a + 3; 
}

function foo(x) { 
  return 8 + x; 
}

Questions to ask when inlining

  • Which functions are important?
  • To what depth?
  • You can do too much...

Array.Prototype.Map

// one of many array "built-ins"

let a = [1, 2, 3];
let mult = x => x * 2;
a.map(mult);
// prints 2, 4, 6

Array.Prototype.Map

// If you wrote it by hand...

let a = [1, 2, 3];
let mult = x => x * 2;
let b = [];
for (let i = 0; i < a.length; i++) {
  b[i] = mult(a[i], i, a);
}
// b is [2, 4, 6]

We can inline Array builtins

  • We know exactly what the function does
  • If we ALSO inline the predicate function, we can really benefit
  • Technical challenge: deoptimization in the middle of the work

Array.Prototype.Map inlining

// Consider this case...
let a = [1, 2, 3];
let mult = x => x * 2;

function foo() {
  return a.map(mult);
}

Array.Prototype.Map inlining

// Consider this case...
let a = [1, 2, 3];
let mult = x => x * 2;

function foo() {
  // we inlined Array.map!
  let b = [];
  for (let i = 0; i < a.length; i++) {
    b[i] = mult(a[i]);
  }
  return b;
}

Array.Prototype.Map inlining

// Consider this case...
let a = [1, 2, 3];
let mult = x => x * 2;

function foo() {
  // we inlined Array.map...also mult.
  let b = [];
  for (let i = 0; i < a.length; i++) {
    b[i] = a[i] * 2;
  }
  return b;
}

Performance "cliffs"

  • Messing with the array prototype...
  • Mixing floating point numbers and integers
  • etc.

Array.Prototype changes

// Arrays can have "holes"
let a = [1, , 3];
a[1];
// prints undefined
// holes "see through" to 
// the prototype
Array.prototype[1] = 'oh hai';
a[1];
// oh hai     :/

Questions?

Google proprietary

Shameless plug

Geektime

By ripsawridge

Geektime

Google Chrome V8

  • 1,265