Know Your Engines
How to Make Your JavaScript Fast Dave Mandelin 8 November 2011 O’Reilly Velocity Europe
Tuesday, November 8, 2011
Know Your Engines How to Make Your JavaScript Fast Dave Mandelin 8 - - PowerPoint PPT Presentation
Know Your Engines How to Make Your JavaScript Fast Dave Mandelin 8 November 2011 OReilly Velocity Europe Tuesday, November 8, 2011 JavaScript is getting really fast and programs are getting crazy Bullet physics engine (ammo.js) H.264
Tuesday, November 8, 2011
Tuesday, November 8, 2011
function f() { var sum = 0; for (var i = 0; i < N; ++i) { sum += i; } } function f() { eval(“”); var sum = 0; for (var i = 0; i < N; ++i) { sum += i; } }
Tuesday, November 8, 2011
function f() { var sum = 0; for (var i = 0; i < N; ++i) { sum += i; } } function f() { eval(“”); var sum = 0; for (var i = 0; i < N; ++i) { sum += i; } }
20 40 60 80 without eval with eval
with eval(“”) up to 10x slower!
Tuesday, November 8, 2011
Or, Not Making JavaScript Slow
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Front End Interpreter DOM Standard Library Garbage Collector
Tuesday, November 8, 2011
Front End
// JavaScript source e.innerHTML = n + “ items”;
Interpreter DOM Standard Library Garbage Collector
Tuesday, November 8, 2011
Front End
// JavaScript source e.innerHTML = n + “ items”; // bytecode (AST in some engines) tmp_0 = add var_1 str_3 setprop var_0 ‘innerHTML’ tmp_0
Interpreter DOM Standard Library Garbage Collector
Tuesday, November 8, 2011
Front End
// JavaScript source e.innerHTML = n + “ items”; // bytecode (AST in some engines) tmp_0 = add var_1 str_3 setprop var_0 ‘innerHTML’ tmp_0
Interpreter DOM Standard Library Garbage Collector
Run the bytecode
Tuesday, November 8, 2011
Front End
// JavaScript source e.innerHTML = n + “ items”; // bytecode (AST in some engines) tmp_0 = add var_1 str_3 setprop var_0 ‘innerHTML’ tmp_0
Interpreter DOM Standard Library Garbage Collector
Run the bytecode Reclaim memory
Tuesday, November 8, 2011
Front End
// JavaScript source e.innerHTML = n + “ items”; // bytecode (AST in some engines) tmp_0 = add var_1 str_3 setprop var_0 ‘innerHTML’ tmp_0
Interpreter DOM Standard Library Garbage Collector
Run the bytecode Set innerHTML Reclaim memory
Tuesday, November 8, 2011
Because JavaScript is an untyped language. untyped = no type declarations
Tuesday, November 8, 2011
x = y + z can mean many things
Tuesday, November 8, 2011
JS engines use finer-grained types internally.
number
JavaScript type
Tuesday, November 8, 2011
JS engines use finer-grained types internally.
number 32-bit* integer 64-bit floating-point
JavaScript type Engine type
Tuesday, November 8, 2011
JS engines use finer-grained types internally.
number 32-bit* integer 64-bit floating-point
JavaScript type Engine type
{ a: 1 } { a: 1, b: 2 } { a: get ... } { a: 1, __proto__ = new C }
Tuesday, November 8, 2011
JS engines use finer-grained types internally.
number 32-bit* integer 64-bit floating-point
JavaScript type Engine type
{ a: 1 } { a: 1, b: 2 } { a: get ... } { a: 1, __proto__ = new C } Different shapes
Tuesday, November 8, 2011
Boxed Unboxed Purpose Storage Computation Examples
(INT, 55) 55 (STRING, “foo”) “foo”
Definition
(type tag, C++ value) C++ value
Because JavaScript is untyped, the interpreter needs boxed values.
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
This is the only real work!
Tuesday, November 8, 2011
Here’s what the interpreter must do to execute x = y + z:
This is the only real work! Everything else is
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Front End
JavaScript source bytecode/AST
Interpreter DOM
Standard Library Garbage Collector
Tuesday, November 8, 2011
Front End
JavaScript source bytecode/AST
Interpreter DOM
Standard Library Garbage Collector
Untyped Compiler
Compile to x86/x64/ARM
Tuesday, November 8, 2011
Front End
JavaScript source bytecode/AST
Interpreter DOM
Standard Library Garbage Collector
Untyped Compiler
Compile to x86/x64/ARM
CPU
Fast!
x86/x64/ARM
Tuesday, November 8, 2011
Front End
JavaScript source bytecode/AST
Interpreter DOM
Standard Library Garbage Collector
Untyped Compiler Typed Compiler
Compile to x86/x64/ARM
CPU
Fast! Ultra Fast!
x86/x64/ARM
Tuesday, November 8, 2011
Front End
JavaScript source bytecode/AST
Interpreter DOM
Standard Library Garbage Collector
Untyped Compiler Typed Compiler
Compile to x86/x64/ARM
CPU
∏
Fast! Ultra Fast!
x86/x64/ARM
Tuesday, November 8, 2011
Front End
JavaScript source bytecode/AST
Interpreter DOM
Standard Library Garbage Collector
Untyped Compiler Typed Compiler
Compile to x86/x64/ARM
CPU
∏
Fast! THE SLOW ZONE Ultra Fast!
x86/x64/ARM
Tuesday, November 8, 2011
The basic JIT compiler on x = y + z:
All Major Browsers
Tuesday, November 8, 2011
The basic JIT compiler on x = y + z:
All Major Browsers
CPU does it for us!
Tuesday, November 8, 2011
The basic JIT compiler on x = y + z:
All Major Browsers
CPU does it for us! JIT code can keep things in registers
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
All Major Browsers
Tuesday, November 8, 2011
function f(obj) { return obj.a + 1; }
Tuesday, November 8, 2011
function f(obj) { return obj.a + 1; }
Tuesday, November 8, 2011
function f(obj) { return obj.a + 1; }
Tuesday, November 8, 2011
function f(obj) { return obj.a + 1; }
Tuesday, November 8, 2011
All Major Browsers
Tuesday, November 8, 2011
All Major Browsers
Tuesday, November 8, 2011
All Major Browsers
Tuesday, November 8, 2011
All Major Browsers
Tuesday, November 8, 2011
All Major Browsers
Tuesday, November 8, 2011
All Major Browsers
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1 shape=12, in position 1
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1 icStub_1: compare obj.shape, 12 jumpIfFalse slowPropAccess load obj.props[1] jump continue_1 shape=12, in position 1
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1 icStub_1: compare obj.shape, 12 jumpIfFalse slowPropAccess load obj.props[1] jump continue_1 shape=12, in position 1
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1 icStub_1: compare obj.shape, 12 jumpIfFalse slowPropAccess load obj.props[1] jump continue_1 shape=12, in position 1
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1 icStub_1: compare obj.shape, 12 jumpIfFalse slowPropAccess load obj.props[1] jump continue_1 shape=12, in position 1 shape=15, in position 0
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1 icStub_1: compare obj.shape, 12 jumpIfFalse slowPropAccess load obj.props[1] jump continue_1 icStub_2: compare obj.shape, 15 jumpIfFalse slowPropAccess load obj.props[0] jump continue_1 shape=12, in position 1 shape=15, in position 0
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1 icStub_1: compare obj.shape, 12 jumpIfFalse slowPropAccess load obj.props[1] jump continue_1 icStub_2: compare obj.shape, 15 jumpIfFalse slowPropAccess load obj.props[0] jump continue_1 shape=12, in position 1 shape=15, in position 0
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) { return obj.b + 1; }
Example Code Generated JIT Code
... jump slowPropAccess continue_1: ... slowPropAccess: ... set up call call ICGetProp ; C++ Slow Zone jump continue_1 icStub_1: compare obj.shape, 12 jumpIfFalse slowPropAccess load obj.props[1] jump continue_1 icStub_2: compare obj.shape, 15 jumpIfFalse slowPropAccess load obj.props[0] jump continue_1 shape=12, in position 1 shape=15, in position 0
Tuesday, November 8, 2011
var q = 4; var r; function f(obj) { r = q; }
Global Variable Access
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) {
}
Direct Property Access
var q = 4; var r; function f(obj) { r = q; }
Global Variable Access
Tuesday, November 8, 2011
var obj1 = { a: 1, b: 2, c: 3 }; var obj2 = { b: 2 }; function f(obj) {
}
Direct Property Access
var q = 4; var r; function f(obj) { r = q; }
Global Variable Access
var f = function() { var x = 1; var g = function() { var sum = 0; for (var i = 0; i < N; ++i) { sum += x; } return sum; } return g(); }
Closure Variable Access
Tuesday, November 8, 2011
function A(x) { this.x = x; } function B(y) { this.y = y; } B.prototype = new A; function C(z) { this.z = z; } C.prototype = new B;
Tuesday, November 8, 2011
new C(1) new B new A function A(x) { this.x = x; } function B(y) { this.y = y; } B.prototype = new A; function C(z) { this.z = z; } C.prototype = new B; proto
Tuesday, November 8, 2011
new C(1) new B new A function A(x) { this.x = x; } function B(y) { this.y = y; } B.prototype = new A; function C(z) { this.z = z; } C.prototype = new B; new C(2) proto
Tuesday, November 8, 2011
new C(1) new B new A function A(x) { this.x = x; } function B(y) { this.y = y; } B.prototype = new A; function C(z) { this.z = z; } C.prototype = new B; new C(2) new C(3) proto
Tuesday, November 8, 2011
new C(1) new B new A function A(x) { this.x = x; } function B(y) { this.y = y; } B.prototype = new A; function C(z) { this.z = z; } C.prototype = new B; new C(2) new C(3)
Shape of new C objects determines prototype
proto
Tuesday, November 8, 2011
new C(1) new B new A function A(x) { this.x = x; } function B(y) { this.y = y; } B.prototype = new A; function C(z) { this.z = z; } C.prototype = new B; new C(2) new C(3)
Shape of new C objects determines prototype
then reads directly from prototype without walking
proto
Tuesday, November 8, 2011
function f(obj) { return obj.p; }
What happens if many shapes of obj are passed to f? ICs end up looking like this:
Tuesday, November 8, 2011
function f(obj) { return obj.p; }
What happens if many shapes of obj are passed to f? ICs end up looking like this:
jumpIf shape != 12 read for shape 12
Tuesday, November 8, 2011
function f(obj) { return obj.p; }
What happens if many shapes of obj are passed to f? ICs end up looking like this:
jumpIf shape != 12 read for shape 12 jumpIf shape != 15 read for shape 15
Tuesday, November 8, 2011
function f(obj) { return obj.p; }
What happens if many shapes of obj are passed to f? ICs end up looking like this:
jumpIf shape != 12 read for shape 12 jumpIf shape != 15 read for shape 15 jumpIf shape != 6 read for shape 6
Tuesday, November 8, 2011
function f(obj) { return obj.p; }
What happens if many shapes of obj are passed to f? ICs end up looking like this:
jumpIf shape != 12 read for shape 12 jumpIf shape != 15 read for shape 15 jumpIf shape != 6 read for shape 6 jumpIf shape != 16 read for shape 16 jumpIf shape != 22 read for shape 22 jumpIf shape != 3 read for shape 3 ...
Tuesday, November 8, 2011
25 50 75 100 1 2 8 16 32 100 200 nanoseconds/iteration # of shapes at property read site
IE Opera Chrome Firefox Safari
IE Slow Zone for 2+ shapes Opera # of shapes doesn’t matter! Chrome more shapes -> slower Firefox slower with more shapes, Safari but levels off in Slow Zone
Tuesday, November 8, 2011
var f = function() { var x; var g = function() { var h = function() { var y; var i = function () { var j = function() { z = x + y;
Tuesday, November 8, 2011
var f = function() { var x; var g = function() { var h = function() { var y; var i = function () { var j = function() { z = x + y; j call object f call object h call object First call to f
Tuesday, November 8, 2011
var f = function() { var x; var g = function() { var h = function() { var y; var i = function () { var j = function() { z = x + y; j call object f call object f call object j call object h call object h call object First call to f Second call to f
Tuesday, November 8, 2011
var f = function() { var x; var g = function() { var h = function() { var y; var i = function () { var j = function() { z = x + y; j call object f call object f call object j call object h call object h call object First call to f Second call to f
Tuesday, November 8, 2011
var f = function() { var x; var g = function() { var h = function() { var y; var i = function () { var j = function() { z = x + y; j call object f call object f call object j call object h call object h call object First call to f Second call to f
Tuesday, November 8, 2011
var f = function() { var x; var g = function() { var h = function() { var y; var i = function () { var j = function() { z = x + y; j call object f call object f call object j call object h call object h call object First call to f Second call to f
Tuesday, November 8, 2011
Tuesday, November 8, 2011
var a = {}; a.x;
Undefined Property
(Fast on Firefox, Chrome)
Tuesday, November 8, 2011
var a = {}; a.x;
Undefined Property
(Fast on Firefox, Chrome) var a = document.getByElementId(“foo”); a.id;
DOM Access
(I only tested .id, so take with a grain of salt--
Tuesday, November 8, 2011
var a = {}; a.x;
Undefined Property
(Fast on Firefox, Chrome) var a = { x: get() { return 1; } }; a.x;
Scripted Getter
(Fast on IE) var a = document.getByElementId(“foo”); a.id;
DOM Access
(I only tested .id, so take with a grain of salt--
Tuesday, November 8, 2011
var a = {}; a.x;
Undefined Property
(Fast on Firefox, Chrome) var a = { x: get() { return 1; } }; a.x;
Scripted Getter
(Fast on IE) var a = { x: set(y) { this.x_ = y; } }; a.x = 1;
Scripted Setter
var a = document.getByElementId(“foo”); a.id;
DOM Access
(I only tested .id, so take with a grain of salt--
Tuesday, November 8, 2011
Firefox 3.5+ (Tracemonkey, JM+TI) Chrome 11+ (Crankshaft)
Tuesday, November 8, 2011
If only JavaScript had type declarations...
Tuesday, November 8, 2011
If only JavaScript had type declarations...
Tuesday, November 8, 2011
If only JavaScript had type declarations...
Tuesday, November 8, 2011
If only JavaScript had type declarations...
Tuesday, November 8, 2011
If only JavaScript had type declarations... I call this kind of JIT a typed compiler
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
On x = y + z:
Firefox 3.5+ Chrome 11+
Tuesday, November 8, 2011
On x = y + z:
Firefox 3.5+ Chrome 11+
Tuesday, November 8, 2011
On x = y + z:
Firefox 3.5+ Chrome 11+
Tuesday, November 8, 2011
function getPop(city) { return popdata[city.id]; } for (var i = 0; i < N; ++i) { total += getPop(city); }
Automatic Inlining
Tuesday, November 8, 2011
function getPop(city) { return popdata[city.id]; } for (var i = 0; i < N; ++i) { total += getPop(city); }
Automatic Inlining
for (var i = 0; i < N; ++i) { total += popdata[city.id]; }
JIT compiles as if you wrote this
Tuesday, November 8, 2011
for (var i = 0; i < N; ++i) { total += a[i] * (1 + options.tax); }
Loop Invariant Code Motion (LICM, “hoisting”)
Tuesday, November 8, 2011
for (var i = 0; i < N; ++i) { total += a[i] * (1 + options.tax); }
Loop Invariant Code Motion (LICM, “hoisting”)
var f = 1 + options.tax; for (var i = 0; i < N; ++i) { total += a[i] * f; }
JIT compiles as if you wrote this
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
The key to running faster in future JITs is type-stable JavaScript. This means JavaScript where you could declare a single engine-internal type for each variable.
Tuesday, November 8, 2011
var g = 34; var o1 = { a: 56 }; var o2 = { a: 99 }; for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; g += o.a; } g = 0;
Type-stable
Tuesday, November 8, 2011
var g = 34; var o1 = { a: 56 }; var o2 = { a: 99 }; for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; g += o.a; } g = 0;
Type-stable NOT type-stable
var g = 34; var o1 = { a: 56 }; var o2 = { z: 22, a: 56 }; for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; g += o.a; } g = “hello”;
Tuesday, November 8, 2011
var g = 34; var o1 = { a: 56 }; var o2 = { a: 99 }; for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; g += o.a; } g = 0;
Type-stable NOT type-stable
var g = 34; var o1 = { a: 56 }; var o2 = { z: 22, a: 56 }; for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; g += o.a; } g = “hello”; Different shapes
Tuesday, November 8, 2011
var g = 34; var o1 = { a: 56 }; var o2 = { a: 99 }; for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; g += o.a; } g = 0;
Type-stable NOT type-stable
var g = 34; var o1 = { a: 56 }; var o2 = { z: 22, a: 56 }; for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; g += o.a; } g = “hello”; Different shapes Type change
Tuesday, November 8, 2011
Tuesday, November 8, 2011
new Object(); new MyConstructor(); { a: 4, b: 5 } Object.create();
Objects
new String(“hello”); “<p>” + e.innerHTML + “</p>”
Strings
new Array(); [ 1, 2, 3, 4 ];
Arrays
Tuesday, November 8, 2011
new Object(); new MyConstructor(); { a: 4, b: 5 } Object.create();
Objects
new String(“hello”); “<p>” + e.innerHTML + “</p>”
Strings
new Array(); [ 1, 2, 3, 4 ];
Arrays
var x = function () { ... } new Function(code);
Function Objects
Tuesday, November 8, 2011
new Object(); new MyConstructor(); { a: 4, b: 5 } Object.create();
Objects
new String(“hello”); “<p>” + e.innerHTML + “</p>”
Strings
new Array(); [ 1, 2, 3, 4 ];
Arrays
var x = function () { ... } new Function(code);
Function Objects
function outer(str) { var name = str; return function inner() { return “Hi, “ + name; } }
Closure Environments
Tuesday, November 8, 2011
new Object(); new MyConstructor(); { a: 4, b: 5 } Object.create();
Objects
new String(“hello”); “<p>” + e.innerHTML + “</p>”
Strings
new Array(); [ 1, 2, 3, 4 ];
Arrays
var x = function () { ... } new Function(code);
Function Objects
function outer(str) { var name = str; return function inner() { return “Hi, “ + name; } }
Closure Environments
name is stored in an implicitly created object!
Tuesday, November 8, 2011
Time JavaScript Running GC Running JS Paused
Tuesday, November 8, 2011
Time JavaScript Running GC Running JS Paused
Tuesday, November 8, 2011
Time JavaScript Running GC Running JS Paused
Tuesday, November 8, 2011
Time JavaScript Running GC Running JS Paused
Tuesday, November 8, 2011
Chrome
Tuesday, November 8, 2011
Idea: Optimize for creating many short-lived objects
Chrome
Tuesday, November 8, 2011
Idea: Optimize for creating many short-lived objects Create objects in a frequently collected nursery area
Chrome
Tuesday, November 8, 2011
Idea: Optimize for creating many short-lived objects Create objects in a frequently collected nursery area Promote long-lived objects to a rarely collected tenured area
Chrome
Tuesday, November 8, 2011
Simple GC JavaScript Running GC Running JS Paused
Idea: Optimize for creating many short-lived objects Create objects in a frequently collected nursery area Promote long-lived objects to a rarely collected tenured area
Chrome
Tuesday, November 8, 2011
Generational GC JavaScript Running Simple GC JavaScript Running GC Running JS Paused
Idea: Optimize for creating many short-lived objects Create objects in a frequently collected nursery area Promote long-lived objects to a rarely collected tenured area
Chrome
Tuesday, November 8, 2011
Generational GC JavaScript Running Simple GC JavaScript Running GC Running JS Paused
Idea: Optimize for creating many short-lived objects Create objects in a frequently collected nursery area Promote long-lived objects to a rarely collected tenured area
nursery collection (<100 us)
Chrome
Tuesday, November 8, 2011
Generational GC JavaScript Running Simple GC JavaScript Running GC Running JS Paused
Idea: Optimize for creating many short-lived objects Create objects in a frequently collected nursery area Promote long-lived objects to a rarely collected tenured area
nursery collection (<100 us) tenured collection
Chrome
Tuesday, November 8, 2011
Generational GC JavaScript Running Simple GC JavaScript Running GC Running JS Paused
Idea: Optimize for creating many short-lived objects Create objects in a frequently collected nursery area Promote long-lived objects to a rarely collected tenured area
nursery collection (<100 us) tenured collection fewer pauses!
Chrome
Tuesday, November 8, 2011
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point Point
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point Point Line
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point Point Line
a b
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point Point Line
a b
Point
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point Point Line
a b
Point Message
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point Point Line
a b
Point Message
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point Point Line
a b
Point Message Point
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Point Point Line
a b
Point Message Point
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Message
scavenging young generation (aka nursery) mark-and-sweep tenured generation
Message Message Array
Tuesday, November 8, 2011
Chrome
Tuesday, November 8, 2011
Idea: Do a little bit of GC traversal at a time
Chrome
Tuesday, November 8, 2011
Simple GC JavaScript Running GC Running JS Paused
Idea: Do a little bit of GC traversal at a time
Chrome
Tuesday, November 8, 2011
Incremental GC Simple GC JavaScript Running GC Running JS Paused
Idea: Do a little bit of GC traversal at a time
Chrome
Tuesday, November 8, 2011
Incremental GC Simple GC JavaScript Running GC Running JS Paused
shorter pauses!
Idea: Do a little bit of GC traversal at a time
Chrome
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
// Prepending example var s = “”; for (var i = 0; i < 100; ++i) { s = i + s; }
Tuesday, November 8, 2011
Want a fast array?
var a = []; for (var i = 0; i < 100; ++i) { a[i] = 0; } var a = []; a[10000] = 0; for (var i = 0; i < 100; ++i) { a[i] = 0; } a.x = 7; // Fx, IE only
fast: dense array 3-15x slower: sparse array
Tuesday, November 8, 2011
// This runs in all in JIT code, // so it’s really fast. for (var i = 0; i < a.length; ++i) { sum += a[i]; }
fastest: index iteration
Tuesday, November 8, 2011
// This runs in all in JIT code, // so it’s really fast. for (var i = 0; i < a.length; ++i) { sum += a[i]; }
fastest: index iteration 3-15x slower: functional style
// This makes N function calls, // and most JITs don’t optimize // through C++ reduce(). sum = a.reduce(function(a, b) { return a + b; });
20-80x slower: for-in
// This calls a C++ function to // navigate the property list. for (var i in a) { sum += a[i]; }
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Creating objects is slow Doesn’t matter too much how you create or populate
Tuesday, November 8, 2011
Creating objects is slow Doesn’t matter too much how you create or populate Exception: Constructors on Chrome are fast
function Cons(x, y, z) { this.x = x; this.y = y; this.z = z; } for (var i = 0; i < N; ++i) new Cons(i, i + 1, i * 2);
Tuesday, November 8, 2011
Tuesday, November 8, 2011
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { distance: function(pt2) ...
Prototype
Tuesday, November 8, 2011
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { distance: function(pt2) ... function Point(x, y) { return { distance: function(pt2) ... } }
Prototype Information-Hiding
Tuesday, November 8, 2011
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { distance: function(pt2) ... function Point(x, y) { return { distance: function(pt2) ... } }
Prototype Information-Hiding
function Point(x, y) { this.x = x; this.y = y; this.distance = function(pt2) ... }
Instance Methods
Tuesday, November 8, 2011
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { distance: function(pt2) ... function Point(x, y) { return { distance: function(pt2) ... } }
Prototype Information-Hiding
function Point(x, y) { this.x = x; this.y = y; this.distance = function(pt2) ... }
Instance Methods Prototype style is much faster to create (each closure creates a function object)
Tuesday, November 8, 2011
function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { distance: function(pt2) ... function Point(x, y) { return { distance: function(pt2) ... } }
Prototype Information-Hiding
function Point(x, y) { this.x = x; this.y = y; this.distance = function(pt2) ... }
Instance Methods Prototype style is much faster to create (each closure creates a function object) Using the objects is about the same
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Short version: Do not use anywhere near performance sensitive code!
var sum = 0; for (var i = 0; i < N; ++i) { sum = eval(“sum + i”); }
Mind-Bogglingly Awful
5-100x slower than using a function call var sum = 0; eval(“”); for (var i = 0; i < N; ++i) { sum = eval(“sum + i”); }
Still Terrible
2-10x slower than without eval
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
Tuesday, November 8, 2011
JS engine developers want to help you. Tell us about:
Tuesday, November 8, 2011