Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Know Your EnginesHow to Make Your JavaScript Fast        Dave Mandelin         June 15, 2011        O’Reilly Velocity
5 years of progress...                 10                                                       JavaScript                ...
...lost in an instant!function f() {  var sum = 0;  for (var i = 0; i < N; ++i) {    sum += i;  }}function f() {    eval(“...
...lost in an instant!function f() {                     80  var sum = 0;  for (var i = 0; i < N; ++i) {    sum += i;     ...
Making JavaScript Fast     Or, Not Making JavaScript SlowHow JITs make JavaScript not slowHow not to ruin animation with p...
The 2006 JavaScript Engine
Inside the 2006 JS Engine                           DOM                          StandardFront End   Interpreter    Librar...
Inside the 2006 JS Engine// JavaScript sourcee.innerHTML = n + “ items”;                  DOM                             ...
Inside the 2006 JS Engine// JavaScript sourcee.innerHTML = n + “ items”;                            DOM                   ...
Inside the 2006 JS Engine// JavaScript sourcee.innerHTML = n + “ items”;                                  DOM             ...
Inside the 2006 JS Engine// JavaScript sourcee.innerHTML = n + “ items”;                                      DOM         ...
Inside the 2006 JS Engine                                                            Set innerHTML// JavaScript sourcee.in...
Why it’s hard to make JS fast                 Because   JavaScript is an untyped language.    untyped = no type declarations
Operations in an untyped language          x = y + z can mean many things  •   if y and z are numbers, numeric addition  •...
Engine-Internal TypesJS engines use finer-grained types internally. JavaScript type   number    object
Engine-Internal TypesJS engines use finer-grained types internally. JavaScript type             Engine type   number       ...
Engine-Internal TypesJS engines use finer-grained types internally. JavaScript type              Engine type   number      ...
Engine-Internal TypesJS engines use finer-grained types internally. JavaScript type              Engine type   number      ...
Values in an untyped languageBecause JavaScript is untyped, the interpreter needs boxed values.                           ...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z:
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z f...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z f...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z f...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣   read the operation x = y + z...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣   read the operation x = y + z...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣   read the operation x = y + z...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣   read the operation x = y + z...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣   read the operation x = y + z...
Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣   read the operation x = y + z...
The 2011 JavaScript Engine
Inside the 2011 JS Engine                                                 Garbage                                         ...
Inside the 2011 JS Engine                                                            Garbage                              ...
Inside the 2011 JS Engine                                                            Garbage                              ...
Inside the 2011 JS Engine                                                            Garbage                              ...
Inside the 2011 JS Engine                                                            Garbage                              ...
Inside the 2011 JS Engine                THE                                         Garbage                              ...
Running Code with the JIT                                                       All Major        The basic JIT compiler on...
Running Code with the JIT                                                      All Major       The basic JIT compiler on x...
Running Code with the JIT                                                         All Major       The basic JIT compiler o...
Choosing the action in the JIT
Choosing the action in the JIT•   Many cases for operators like +
Choosing the action in the JIT•   Many cases for operators like +•   Engines generate fast JIT code for “common cases”    ...
Choosing the action in the JIT•   Many cases for operators like +•   Engines generate fast JIT code for “common cases”    ...
JITs for Regular Expressions                                                              All Major                       ...
Object Properties  function f(obj) {    return obj.a + 1;  }
Object Properties                     function f(obj) {                       return obj.a + 1;                     }•   N...
Object Properties                      function f(obj) {                        return obj.a + 1;                      }• ...
Object Properties                       function f(obj) {                         return obj.a + 1;                       ...
ICs: a mini-JIT for objects   All Major                              Browsers
ICs: a mini-JIT for objects                       All Major                                                          Brows...
ICs: a mini-JIT for objects                      All Major                                                          Browse...
ICs: a mini-JIT for objects                          All Major                                                            ...
ICs: a mini-JIT for objects                            All Major                                                          ...
ICs: a mini-JIT for objects                            All Major                                                          ...
ICs: Example          Example Codevar obj1 = { a: 1, b: 2, c: 3 };var obj2 = { b: 2 };function f(obj) {  return obj.b + 1;}
ICs: Example          Example Codevar obj1 = { a: 1, b: 2, c: 3 };var obj2 = { b: 2 };function f(obj) {  return obj.b + 1;...
ICs: Example         Example Code                            shape=12, in position 1var obj1 = { a: 1, b: 2, c: 3 };var ob...
ICs: Example         Example Code                                 icStub_1:                            shape=12, in positi...
ICs: Example         Example Code                                 icStub_1:                            shape=12, in positi...
ICs: Example         Example Code                                 icStub_1:                            shape=12, in positi...
ICs: Example         Example Code                                 icStub_1:                            shape=12, in positi...
ICs: Example         Example Code                                 icStub_1:                            shape=12, in positi...
ICs: Example         Example Code                                 icStub_1:                            shape=12, in positi...
ICs: Example         Example Code                                 icStub_1:                            shape=12, in positi...
These are fast because of ICs  Global Variable Accessvar q = 4;var r;function f(obj) {  r = q;}
These are fast because of ICs   Global Variable Accessvar q = 4;var r;function f(obj) {  r = q;}  Direct Property Accessva...
These are fast because of ICs   Global Variable Access           Closure Variable Accessvar q = 4;                        ...
Prototypes don’t hurt muchfunction A(x) {  this.x = x;}function B(y) {  this.y = y;}B.prototype = new A;function C(z) {  t...
Prototypes don’t hurt much                                     new Afunction A(x) {  this.x = x;}                         ...
Prototypes don’t hurt much                                      new Afunction A(x) {  this.x = x;}                        ...
Prototypes don’t hurt much                                      new Afunction A(x) {  this.x = x;}                        ...
Prototypes don’t hurt much                                          new Afunction A(x) {  this.x = x;}                    ...
Prototypes don’t hurt much                                                new Afunction A(x) {  this.x = x;}              ...
Many Shapes Slow Down ICsWhat happens if many shapes of obj are passed to f?            function f(obj) {              ret...
Many Shapes Slow Down ICs         What happens if many shapes of obj are passed to f?                      function f(obj)...
Many Shapes Slow Down ICs         What happens if many shapes of obj are passed to f?                              functio...
Many Shapes Slow Down ICs         What happens if many shapes of obj are passed to f?                              functio...
Many Shapes Slow Down ICs         What happens if many shapes of obj are passed to f?                              functio...
Many shapes in practice                        100                                      IE                                ...
Deeply Nested Closures are Slowervar f = function() { var x; var g = function() {  var h = function() {    var y;    var i...
Deeply Nested Closures are Slowervar f = function() {         f call object var x; var g = function() {  var h = function(...
Deeply Nested Closures are Slowervar f = function() {         f call object      f call object var x; var g = function() {...
Deeply Nested Closures are Slowervar f = function() {                     f call object      f call object var x; var g = ...
Deeply Nested Closures are Slowervar f = function() {                      f call object      f call object var x; var g =...
Deeply Nested Closures are Slowervar f = function() {                      f call object      f call object var x; var g =...
Properties in the Slow Zone
Properties in the Slow Zone     Undefined Property       (Fast on Firefox, Chrome)var a = {};a.x;
Properties in the Slow Zone        Undefined Property           (Fast on Firefox, Chrome)   var a = {};   a.x;             ...
Properties in the Slow Zone        Undefined Property                                       Scripted Getter           (Fast...
Properties in the Slow Zone        Undefined Property                                        Scripted Getter           (Fas...
The Type-Specializing JIT                        Firefox 3.5+                      (Tracemonkey)                       Chr...
Types FTW!If only JavaScript had type declarations...
Types FTW!        If only JavaScript had type declarations...➡ The JIT would know the type of every local variable
Types FTW!        If only JavaScript had type declarations...➡ The JIT would know the type of every local variable ➡ Know ...
Types FTW!        If only JavaScript had type declarations...➡ The JIT would know the type of every local variable ➡ Know ...
Types FTW!        If only JavaScript had type declarations...➡ The JIT would know the type of every local variable ➡ Know ...
But JS doesn’t have types
But JS doesn’t have types• Problem: JS doesn’t have type declarations • won’t have them any time soon • we don’t want to w...
But JS doesn’t have types• Problem: JS doesn’t have type declarations • won’t have them any time soon • we don’t want to w...
But JS doesn’t have types• Problem: JS doesn’t have type declarations • won’t have them any time soon • we don’t want to w...
Running with the Type-Specializing JIT                                                          Firefox 3.5+              ...
Running with the Type-Specializing JIT                                                          Firefox 3.5+              ...
Running with the Type-Specializing JIT                                                          Firefox 3.5+              ...
Further Optimization 1                                Automatic Inlining        original codefunction getPop(city) {  retu...
Further Optimization 1                                Automatic Inlining        original code                             ...
Further Optimization 2        Loop Invariant Code Motion (LICM, “hoisting”)        original codefor (var i = 0; i < N; ++i...
Further Optimization 2        Loop Invariant Code Motion (LICM, “hoisting”)        original code                  JIT comp...
Optimize Only Hot Code
Optimize Only Hot Code•   Type-specializing JITs can have a hefty startup cost    •   Need to collect the type information...
Optimize Only Hot Code•   Type-specializing JITs can have a hefty startup cost    •   Need to collect the type information...
Current Limitations
Current Limitations• What happens if the types change after compiling? •   Just a few changes -> recompile, slight slowdow...
Current Limitations• What happens if the types change after compiling?    •   Just a few changes -> recompile, slight slow...
Current Limitations• What happens if the types change after compiling?    •   Just a few changes -> recompile, slight slow...
Type Inference for JITs                          Current                          Research                          @Mozilla
Type Inference
Type Inference•   Trying to get rid of the last few instances of boxing    (from before: array and object properties)
Type Inference•   Trying to get rid of the last few instances of boxing    (from before: array and object properties)•   I...
Type Inference Example var a = []; for (var i = 0; i < N; ++i) {   a[i] = i * i; ] var sum = 0; for (var i = 0; i < N; ++i...
Type Inference Example var a = []; for (var i = 0; i < N; ++i) {   a[i] = i * i; ] var sum = 0; for (var i = 0; i < N; ++i...
Type Inference Example var a = [];                      var a = []; for (var i = 0; i < N; ++i) {    for (var i = 0; i < N...
Type-stable JavaScript      The key to running faster in future JITs is                type-stable JavaScript.        This...
Type-stable JS: examples         Type-stablevar g = 34;var o1 = { a: 56 };var o2 = { a: 99 };for (var i = 0; i < 10; ++i) ...
Type-stable JS: examples         Type-stable                 NOT type-stablevar g = 34;                      var g = 34;va...
Type-stable JS: examples         Type-stable                 NOT type-stablevar g = 34;                      var g = 34;va...
Type-stable JS: examples         Type-stable                 NOT type-stablevar g = 34;                      var g = 34;va...
Garbage Collection
What Allocates Memory?              Objectsnew Object();new MyConstructor();{ a: 4, b: 5 }Object.create();                ...
What Allocates Memory?              Objects               Function Objectsnew Object();                  var x = function ...
What Allocates Memory?              Objects               Function Objectsnew Object();                  var x = function ...
What Allocates Memory?              Objects                   Function Objectsnew Object();                      var x = f...
GC Pauses Your Program!Time   JavaScript   GC Running        Running      JS Paused
GC Pauses Your Program!Time           JavaScript    GC Running                Running       JS Paused       •   Basic GC a...
GC Pauses Your Program!Time           JavaScript    GC Running                Running       JS Paused       •   Basic GC a...
GC Pauses Your Program!Time           JavaScript    GC Running                Running       JS Paused       •   Basic GC a...
Reducing Pauses with Science 1        Generational GC    Chrome
Reducing Pauses with Science 1             Generational GC                            Chrome Idea: Optimize for creating m...
Reducing Pauses with Science 1              Generational GC                              Chrome Idea: Optimize for creatin...
Reducing Pauses with Science 1               Generational GC                                   Chrome Idea: Optimize for c...
Reducing Pauses with Science 1                     Generational GC                                  Chrome       Idea: Opt...
Reducing Pauses with Science 1                            Generational GC                                  Chrome         ...
Reducing Pauses with Science 1                            Generational GC                                  Chrome         ...
Reducing Pauses with Science 1                            Generational GC                                   Chrome        ...
Reducing Pauses with Science 1                            Generational GC                                   Chrome        ...
Generational GC by Examplescavenging young generation (aka nursery)mark-and-sweep tenured generation                  Mess...
Generational GC by Examplescavenging young generation (aka nursery)  Pointmark-and-sweep tenured generation               ...
Generational GC by Examplescavenging young generation (aka nursery)  Point   Pointmark-and-sweep tenured generation       ...
Generational GC by Examplescavenging young generation (aka nursery)  Point   Point    Linemark-and-sweep tenured generatio...
Generational GC by Examplescavenging young generation (aka nursery)  Point   Point       Line                  a      bmar...
Generational GC by Examplescavenging young generation (aka nursery)  Point   Point       Line      Point                  ...
Generational GC by Examplescavenging young generation (aka nursery)  Point   Point       Line      Point   Message        ...
Generational GC by Examplescavenging young generation (aka nursery)  Point   Point       Line      Point   Message        ...
Generational GC by Examplescavenging young generation (aka nursery)  Point   Point       Line      Point   Message   Point...
Generational GC by Examplescavenging young generation (aka nursery)  Point   Point       Line      Point              Poin...
Generational GC by Examplescavenging young generation (aka nursery)mark-and-sweep tenured generation                      ...
Reducing Pauses with Science 1I                            Current         Incremental GC     Research                    ...
Reducing Pauses with Science 1I                                                      Current              Incremental GC  ...
Reducing Pauses with Science 1I                                                              Current                      ...
Reducing Pauses with Science 1I                                                                   Current                 ...
Reducing Pauses with Science 1I                                                                   Current                 ...
Reducing Pauses in Practice
Reducing Pauses in Practice•   For all GCs    •   Fewer live objects -> shorter pauses (if not incremental),              ...
Reducing Pauses in Practice•   For all GCs    •   Fewer live objects -> shorter pauses (if not incremental),              ...
Reducing Pauses in Practice•   For all GCs    •   Fewer live objects -> shorter pauses (if not incremental),              ...
JavaScript Engines in Practice
Performance Faults•   Performance fault: when a tiny change hurts performance    •   Sometimes, just makes one statement s...
Strings
Strings•   In the Slow Zone, but some things are faster than you might think
Strings•   In the Slow Zone, but some things are faster than you might think•   .substring() is fast, O(1)    •   Don’t ne...
Strings•   In the Slow Zone, but some things are faster than you might think•   .substring() is fast, O(1)    •   Don’t ne...
Strings•   In the Slow Zone, but some things are faster than you might think•   .substring() is fast, O(1)         // Prep...
Arrays         fast: dense arrayvar a = [];                                       Want a fast array?for (var i = 0; i < 10...
Iteration over Arraysfastest: index iteration// This runs in all in JIT code,// so it’s really fast.for (var i = 0; i < a....
Iteration over Arrays                                       3-15x slower: functional style                                ...
Functions•   Function calls use ICs, so they are fast    •   Manual inlining can still help sometimes•   Key performance f...
Creating Objects              Creating objects is slowDoesn’t matter too much how you create or populate
Creating Objects              Creating objects is slowDoesn’t matter too much how you create or populate    Exception: Con...
OOP Styling
OOP Styling         Prototypefunction Point(x, y) {  this.x = x;  this.y = y;}Point.prototype = {  distance: function(pt2)...
OOP Styling         Prototype                        Information-Hidingfunction Point(x, y) {  this.x = x;                ...
OOP Styling         Prototype                        Information-Hidingfunction Point(x, y) {  this.x = x;                ...
OOP Styling         Prototype                            Information-Hidingfunction Point(x, y) {  this.x = x;            ...
OOP Styling         Prototype                            Information-Hidingfunction Point(x, y) {  this.x = x;            ...
Exceptions•   Exceptions assumed to be rare in perf-sensitive code    •   running a try statement is free on most browers ...
eval and with                             Short version:          Do not use anywhere near performance sensitive code! Min...
Top 5 Things to Know
Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code
Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code4. Avoid creating objects in hot loops
Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code4. Avoid creating objects in hot loops3. Use de...
Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code4. Avoid creating objects in hot loops3. Use de...
Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code4. Avoid creating objects in hot loops3. Use de...
Talk To UsJS engine developers want to help you. Tell us about:   •   Performance faults you run into   •   Exciting apps ...
Upcoming SlideShare
Loading in …5
×

Know your Javascript Engine

5,680 views

Published on

  • Be the first to comment

Know your Javascript Engine

  1. 1. Know Your EnginesHow to Make Your JavaScript Fast Dave Mandelin June 15, 2011 O’Reilly Velocity
  2. 2. 5 years of progress... 10 JavaScript 7.5 Crun time vs. C 5 2.5 0 2006 2008 2011 one program on one popular browser: 10x faster!
  3. 3. ...lost in an instant!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; }}
  4. 4. ...lost in an instant!function f() { 80 var sum = 0; for (var i = 0; i < N; ++i) { sum += i; 60 }} 40 20function f() { eval(“”); 0 without eval with eval var sum = 0; for (var i = 0; i < N; ++i) { sum += i; with eval(“”) up to} } 10x slower!
  5. 5. Making JavaScript Fast Or, Not Making JavaScript SlowHow JITs make JavaScript not slowHow not to ruin animation with pausesHow to write JavaScript that’s not slow
  6. 6. The 2006 JavaScript Engine
  7. 7. Inside the 2006 JS Engine DOM StandardFront End Interpreter Library Garbage Collector
  8. 8. Inside the 2006 JS Engine// JavaScript sourcee.innerHTML = n + “ items”; DOM Standard Front End Interpreter Library Garbage Collector
  9. 9. Inside the 2006 JS Engine// JavaScript sourcee.innerHTML = n + “ items”; DOM Standard Front End Interpreter Library // bytecode (AST in some engines) Garbage tmp_0 = add var_1 str_3 Collector setprop var_0 ‘innerHTML’ tmp_0
  10. 10. Inside the 2006 JS Engine// JavaScript sourcee.innerHTML = n + “ items”; DOM Standard Front End Interpreter Library Run the bytecode // bytecode (AST in some engines) Garbage tmp_0 = add var_1 str_3 Collector setprop var_0 ‘innerHTML’ tmp_0
  11. 11. Inside the 2006 JS Engine// JavaScript sourcee.innerHTML = n + “ items”; DOM Standard Front End Interpreter Library Run the bytecode Reclaim memory // bytecode (AST in some engines) Garbage tmp_0 = add var_1 str_3 Collector setprop var_0 ‘innerHTML’ tmp_0
  12. 12. Inside the 2006 JS Engine Set innerHTML// JavaScript sourcee.innerHTML = n + “ items”; DOM Standard Front End Interpreter Library Run the bytecode Reclaim memory // bytecode (AST in some engines) Garbage tmp_0 = add var_1 str_3 Collector setprop var_0 ‘innerHTML’ tmp_0
  13. 13. Why it’s hard to make JS fast Because JavaScript is an untyped language. untyped = no type declarations
  14. 14. Operations in an untyped language x = y + z can mean many things • if y and z are numbers, numeric addition • if y and z are strings, concatenation • and many other cases; y and z can have different types
  15. 15. Engine-Internal TypesJS engines use finer-grained types internally. JavaScript type number object
  16. 16. Engine-Internal TypesJS engines use finer-grained types internally. JavaScript type Engine type number 32-bit* integer 64-bit floating-point object
  17. 17. Engine-Internal TypesJS engines use finer-grained types internally. JavaScript type Engine type number 32-bit* integer 64-bit floating-point { a: 1 } { a: 1, b: 2 } object { a: get ... } { a: 1, __proto__ = new C }
  18. 18. Engine-Internal TypesJS engines use finer-grained types internally. JavaScript type Engine type number 32-bit* integer 64-bit floating-point { a: 1 } { a: 1, b: 2 } Different object { a: get ... } shapes { a: 1, __proto__ = new C }
  19. 19. Values in an untyped languageBecause JavaScript is untyped, the interpreter needs boxed values. Boxed Unboxed Purpose Storage Computation Examples (INT, 55) 55 (STRING, “foo”) “foo” Definition (type tag, C++ value) C++ value only boxed values can be stored in variables, only unboxed values can be computed with (+, *, etc)
  20. 20. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z:
  21. 21. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory
  22. 22. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory ‣ read the boxed inputs y and z from memory
  23. 23. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory ‣ read the boxed inputs y and z from memory ‣ check the types of y and z and choose the action
  24. 24. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory ‣ read the boxed inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z
  25. 25. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory ‣ read the boxed inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z ‣ execute the action
  26. 26. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory ‣ read the boxed inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z ‣ execute the action ‣ box the output x
  27. 27. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory ‣ read the boxed inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z ‣ execute the action ‣ box the output x ‣ write the boxed output x to memory
  28. 28. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory ‣ read the boxed inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z This is the only real work! ‣ execute the action ‣ box the output x ‣ write the boxed output x to memory
  29. 29. Running Code in the Interpreter Here’s what the interpreter must do to execute x = y + z: ‣ read the operation x = y + z from memory ‣ read the boxed inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z This is the only real work! ‣ execute the action ‣ box the output x Everything else is ‣ write the boxed output x to memory overhead.
  30. 30. The 2011 JavaScript Engine
  31. 31. Inside the 2011 JS Engine Garbage Collector DOM InterpreterJavaScript source Standard Library Front End bytecode/AST
  32. 32. Inside the 2011 JS Engine Garbage Collector DOM InterpreterJavaScript source Standard Library Front End JIT Compiler Compile to x86/x64/ARM bytecode/AST
  33. 33. Inside the 2011 JS Engine Garbage Collector DOM InterpreterJavaScript source Standard Library Fast! x86/x64/ARM Front End JIT Compiler Compile to x86/x64/ARM CPU bytecode/AST
  34. 34. Inside the 2011 JS Engine Garbage Collector DOM InterpreterJavaScript source Standard Library Fast! x86/x64/ARM Front End JIT Compiler Compile to x86/x64/ARM CPU Type-Specializing bytecode/AST JIT Compiler Ultra Fast!
  35. 35. Inside the 2011 JS Engine Garbage Collector DOM InterpreterJavaScript source Standard Library Fast! x86/x64/ARM Front End JIT Compiler Compile to x86/x64/ARM CPU Type-Specializing bytecode/AST JIT Compiler Ultra Fast!
  36. 36. Inside the 2011 JS Engine THE Garbage DOM Collector SLOW ZONE InterpreterJavaScript source Standard Library Fast! x86/x64/ARM Front End JIT Compiler Compile to x86/x64/ARM CPU Type-Specializing bytecode/AST JIT Compiler Ultra Fast!
  37. 37. Running Code with the JIT All Major The basic JIT compiler on x = y + z: Browsers‣ read the operation x = y + z from memory‣ read the inputs y and z from memory‣ check the types of y and z and choose the action‣ unbox y and z‣ execute the action‣ box the output x‣ write the output x to memory
  38. 38. Running Code with the JIT All Major The basic JIT compiler on x = y + z: Browsers‣ read the operation x = y + z from memory CPU does it for us!‣ read the inputs y and z from memory‣ check the types of y and z and choose the action‣ unbox y and z‣ execute the action‣ box the output x‣ write the output x to memory
  39. 39. Running Code with the JIT All Major The basic JIT compiler on x = y + z: Browsers‣ read the operation x = y + z from memory CPU does it for us!‣ read the inputs y and z from memory‣ check the types of y and z and choose the action‣ unbox y and z‣ execute the action‣ box the output x‣ write the output x to memory JIT code can keep things in registers
  40. 40. Choosing the action in the JIT
  41. 41. Choosing the action in the JIT• Many cases for operators like +
  42. 42. Choosing the action in the JIT• Many cases for operators like +• Engines generate fast JIT code for “common cases” • number + number • string + string
  43. 43. Choosing the action in the JIT• Many cases for operators like +• Engines generate fast JIT code for “common cases” • number + number • string + string• “Rare cases” run in the slow zone • number + undefined
  44. 44. JITs for Regular Expressions All Major Browsers• There is a separate JIT for regular expressions• Regular expressions are generally faster than manual search• Still in the slow zone: • Some complex regexes (example: backreferences) • Building result arrays (test much faster than exec)
  45. 45. Object Properties function f(obj) { return obj.a + 1; }
  46. 46. Object Properties function f(obj) { return obj.a + 1; }• Need to search obj for a property named a slow
  47. 47. Object Properties function f(obj) { return obj.a + 1; }• Need to search obj for a property named a slow• May need to search prototype chain up several levels super-slow
  48. 48. Object Properties function f(obj) { return obj.a + 1; }• Need to search obj for a property named a slow• May need to search prototype chain up several levels super-slow• Finally, once we’ve found it, get the property value fast!
  49. 49. ICs: a mini-JIT for objects All Major Browsers
  50. 50. ICs: a mini-JIT for objects All Major Browsers• Properties become fast with inline caching (we prefer IC)
  51. 51. ICs: a mini-JIT for objects All Major Browsers• Properties become fast with inline caching (we prefer IC)• Basic plan:
  52. 52. ICs: a mini-JIT for objects All Major Browsers• Properties become fast with inline caching (we prefer IC)• Basic plan: 1. First time around, search for the property in the Slow Zone
  53. 53. ICs: a mini-JIT for objects All Major Browsers• Properties become fast with inline caching (we prefer IC)• Basic plan: 1. First time around, search for the property in the Slow Zone 2. But record the steps done to actually get the property
  54. 54. ICs: a mini-JIT for objects All Major Browsers• Properties become fast with inline caching (we prefer IC)• Basic plan: 1. First time around, search for the property in the Slow Zone 2. But record the steps done to actually get the property 3. Then JIT a little piece of code that does just that
  55. 55. ICs: Example Example Codevar obj1 = { a: 1, b: 2, c: 3 };var obj2 = { b: 2 };function f(obj) { return obj.b + 1;}
  56. 56. ICs: Example Example Codevar obj1 = { a: 1, b: 2, c: 3 };var obj2 = { b: 2 };function f(obj) { return obj.b + 1;} Generated JIT Code ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  57. 57. ICs: Example Example Code shape=12, in position 1var obj1 = { a: 1, b: 2, c: 3 };var obj2 = { b: 2 };function f(obj) { return obj.b + 1;} Generated JIT Code ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  58. 58. ICs: Example Example Code icStub_1: shape=12, in position 1 compare obj.shape, 12var obj1 = { a: 1, b: 2, c: 3 }; jumpIfFalse slowPropAccessvar obj2 = { b: 2 }; load obj.props[1] jump continue_1function f(obj) { return obj.b + 1;} Generated JIT Code ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  59. 59. ICs: Example Example Code icStub_1: shape=12, in position 1 compare obj.shape, 12var obj1 = { a: 1, b: 2, c: 3 }; jumpIfFalse slowPropAccessvar obj2 = { b: 2 }; load obj.props[1] jump continue_1function f(obj) { return obj.b + 1;} Generated JIT Code ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  60. 60. ICs: Example Example Code icStub_1: shape=12, in position 1 compare obj.shape, 12var obj1 = { a: 1, b: 2, c: 3 }; jumpIfFalse slowPropAccessvar obj2 = { b: 2 }; load obj.props[1] jump continue_1function f(obj) { return obj.b + 1;} Generated JIT Code ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  61. 61. ICs: Example Example Code icStub_1: shape=12, in position 1 compare obj.shape, 12var obj1 = { a: 1, b: 2, c: 3 }; jumpIfFalse slowPropAccessvar obj2 = { b: 2 }; load obj.props[1] shape=15, in position 0 jump continue_1function f(obj) { return obj.b + 1;} Generated JIT Code ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  62. 62. ICs: Example Example Code icStub_1: shape=12, in position 1 compare obj.shape, 12var obj1 = { a: 1, b: 2, c: 3 }; jumpIfFalse slowPropAccessvar obj2 = { b: 2 }; load obj.props[1] shape=15, in position 0 jump continue_1function f(obj) { return obj.b + 1;} icStub_2: compare obj.shape, 15 jumpIfFalse slowPropAccess Generated JIT Code load obj.props[0] jump continue_1 ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  63. 63. ICs: Example Example Code icStub_1: shape=12, in position 1 compare obj.shape, 12var obj1 = { a: 1, b: 2, c: 3 }; jumpIfFalse slowPropAccessvar obj2 = { b: 2 }; load obj.props[1] shape=15, in position 0 jump continue_1function f(obj) { return obj.b + 1;} icStub_2: compare obj.shape, 15 jumpIfFalse slowPropAccess Generated JIT Code load obj.props[0] jump continue_1 ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  64. 64. ICs: Example Example Code icStub_1: shape=12, in position 1 compare obj.shape, 12var obj1 = { a: 1, b: 2, c: 3 }; jumpIfFalse slowPropAccessvar obj2 = { b: 2 }; load obj.props[1] shape=15, in position 0 jump continue_1function f(obj) { return obj.b + 1;} icStub_2: compare obj.shape, 15 jumpIfFalse slowPropAccess Generated JIT Code load obj.props[0] jump continue_1 ... jump slowPropAccess slowPropAccess:continue_1: ... set up call ... call ICGetProp ; C++ Slow Zone jump continue_1
  65. 65. These are fast because of ICs Global Variable Accessvar q = 4;var r;function f(obj) { r = q;}
  66. 66. These are fast because of ICs Global Variable Accessvar q = 4;var r;function f(obj) { r = q;} Direct Property Accessvar obj1 = { a: 1, b: 2, c: 3 };var obj2 = { b: 2 };function f(obj) { obj2.b = obj1.c;}
  67. 67. These are fast because of ICs Global Variable Access Closure Variable Accessvar q = 4; var f = function() {var r; var x = 1; var g = function() {function f(obj) { var sum = 0; r = q; for (var i = 0; i < N; ++i) {} sum += x; } return sum; Direct Property Access } return g();var obj1 = { a: 1, b: 2, c: 3 }; }var obj2 = { b: 2 };function f(obj) { obj2.b = obj1.c;}
  68. 68. Prototypes don’t hurt muchfunction 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;
  69. 69. Prototypes don’t hurt much new Afunction A(x) { this.x = x;} new Bfunction B(y) { proto this.y = y;} new C(1)B.prototype = new A;function C(z) { this.z = z;}C.prototype = new B;
  70. 70. Prototypes don’t hurt much new Afunction A(x) { this.x = x;} new Bfunction B(y) { proto this.y = y;} new C(1) new C(2)B.prototype = new A;function C(z) { this.z = z;}C.prototype = new B;
  71. 71. Prototypes don’t hurt much new Afunction A(x) { this.x = x;} new Bfunction B(y) { proto this.y = y;} new C(1) new C(2) new C(3)B.prototype = new A;function C(z) { this.z = z;}C.prototype = new B;
  72. 72. Prototypes don’t hurt much new Afunction A(x) { this.x = x;} new Bfunction B(y) { proto this.y = y;} new C(1) new C(2) new C(3)B.prototype = new A;function C(z) { this.z = z; Shape of new C objects determines prototype}C.prototype = new B;
  73. 73. Prototypes don’t hurt much new Afunction A(x) { this.x = x;} new Bfunction B(y) { proto this.y = y;} new C(1) new C(2) new C(3)B.prototype = new A;function C(z) { this.z = z; Shape of new C objects determines prototype}C.prototype = new B; -> IC can generate code that checks shape, then reads directly from prototype without walking
  74. 74. Many Shapes Slow Down ICsWhat happens if many shapes of obj are passed to f? function f(obj) { return obj.p; } ICs end up looking like this:
  75. 75. Many Shapes Slow Down ICs What happens if many shapes of obj are passed to f? function f(obj) { return obj.p; } ICs end up looking like this:jumpIf shape != 12read for shape 12
  76. 76. Many Shapes Slow Down ICs What happens if many shapes of obj are passed to f? function f(obj) { return obj.p; } ICs end up looking like this:jumpIf shape != 12read for shape 12 jumpIf shape != 15 read for shape 15
  77. 77. Many Shapes Slow Down ICs What happens if many shapes of obj are passed to f? function f(obj) { return obj.p; } ICs end up looking like this:jumpIf shape != 12read for shape 12 jumpIf shape != 15 read for shape 15 jumpIf shape != 6 read for shape 6
  78. 78. Many Shapes Slow Down ICs What happens if many shapes of obj are passed to f? function f(obj) { return obj.p; } ICs end up looking like this: ...jumpIf shape != 12 jumpIf shape != 16read for shape 12 read for shape 16 jumpIf shape != 15 jumpIf shape != 22 read for shape 15 read for shape 22 jumpIf shape != 6 jumpIf shape != 3 read for shape 6 read for shape 3
  79. 79. Many shapes in practice 100 IE IE Slow Zone for 2+ shapes Opera Chrome 75 Opera # of shapes doesn’t matter!nanoseconds/iteration Firefox Safari 50 Chrome more shapes -> slower Firefox 25 slower with more shapes, but levels off in Slow Zone Safari 0 1 2 8 16 32 100 200 # of shapes at property read site
  80. 80. Deeply Nested Closures are Slowervar f = function() { var x; var g = function() { var h = function() { var y; var i = function () { var j = function() { z = x + y;
  81. 81. Deeply Nested Closures are Slowervar f = function() { f call object var x; var g = function() { var h = function() { h call object var y; var i = function () { var j = function() { j call object z = x + y; First call to f
  82. 82. Deeply Nested Closures are Slowervar f = function() { f call object f call object var x; var g = function() { var h = function() { h call object h call object var y; var i = function () { var j = function() { j call object j call object z = x + y; First call to f Second call to f
  83. 83. Deeply Nested Closures are Slowervar f = function() { f call object f call object var x; var g = function() { var h = function() { h call object h call object var y; var i = function () { var j = function() { j call object j call object z = x + y; First call to f Second call to f• Prototype chains don’t slow us down, but deep closure nesting does. Why?
  84. 84. Deeply Nested Closures are Slowervar f = function() { f call object f call object var x; var g = function() { var h = function() { h call object h call object var y; var i = function () { var j = function() { j call object j call object z = x + y; First call to f Second call to f• Prototype chains don’t slow us down, but deep closure nesting does. Why?• Every call to f generates a unique closure object to hold x.
  85. 85. Deeply Nested Closures are Slowervar f = function() { f call object f call object var x; var g = function() { var h = function() { h call object h call object var y; var i = function () { var j = function() { j call object j call object z = x + y; First call to f Second call to f• Prototype chains don’t slow us down, but deep closure nesting does. Why?• Every call to f generates a unique closure object to hold x.• The engine must walk up to x each time
  86. 86. Properties in the Slow Zone
  87. 87. Properties in the Slow Zone Undefined Property (Fast on Firefox, Chrome)var a = {};a.x;
  88. 88. Properties in the Slow Zone Undefined Property (Fast on Firefox, Chrome) var a = {}; a.x; DOM Access(I only tested .id, so take with a grain of salt-- other properties may differ)var a = document.getByElementId(“foo”);a.id;
  89. 89. Properties in the Slow Zone Undefined Property Scripted Getter (Fast on Firefox, Chrome) (Fast on IE) var a = {}; var a = { x: get() { return 1; } }; a.x; a.x; DOM Access(I only tested .id, so take with a grain of salt-- other properties may differ)var a = document.getByElementId(“foo”);a.id;
  90. 90. Properties in the Slow Zone Undefined Property Scripted Getter (Fast on Firefox, Chrome) (Fast on IE) var a = {}; var a = { x: get() { return 1; } }; a.x; a.x; DOM Access Scripted Setter(I only tested .id, so take with a grain of salt-- other properties may differ) var a = { x: set(y) { this.x_ = y; } }; a.x = 1;var a = document.getByElementId(“foo”);a.id;
  91. 91. The Type-Specializing JIT Firefox 3.5+ (Tracemonkey) Chrome 11+ (Crankshaft)
  92. 92. Types FTW!If only JavaScript had type declarations...
  93. 93. Types FTW! If only JavaScript had type declarations...➡ The JIT would know the type of every local variable
  94. 94. Types FTW! If only JavaScript had type declarations...➡ The JIT would know the type of every local variable ➡ Know exactly what action to use (no type checks)
  95. 95. Types FTW! If only JavaScript had type declarations...➡ The JIT would know the type of every local variable ➡ Know exactly what action to use (no type checks) ➡ Local variables don’t need to be boxed (or unboxed)
  96. 96. Types FTW! If only JavaScript had type declarations...➡ The JIT would know the type of every local variable ➡ Know exactly what action to use (no type checks) ➡ Local variables don’t need to be boxed (or unboxed) We call this kind of JIT a type-specializing JIT
  97. 97. But JS doesn’t have types
  98. 98. But JS doesn’t have types• Problem: JS doesn’t have type declarations • won’t have them any time soon • we don’t want to wait
  99. 99. But JS doesn’t have types• Problem: JS doesn’t have type declarations • won’t have them any time soon • we don’t want to wait• Solution: run the program for a bit, monitor types
  100. 100. But JS doesn’t have types• Problem: JS doesn’t have type declarations • won’t have them any time soon • we don’t want to wait• Solution: run the program for a bit, monitor types• Then recompile optimized for those types
  101. 101. Running with the Type-Specializing JIT Firefox 3.5+ On x = y + z: Chrome 11+ ‣ read the operation x = y + z from memory ‣ read the inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z ‣ execute the action ‣ box the output x ‣ write the output x to memory
  102. 102. Running with the Type-Specializing JIT Firefox 3.5+ On x = y + z: Chrome 11+ ‣ read the operation x = y + z from memory ‣ read the inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z ‣ execute the action ‣ box the output x ‣ write the output x to memory
  103. 103. Running with the Type-Specializing JIT Firefox 3.5+ On x = y + z: Chrome 11+ ‣ read the operation x = y + z from memory ‣ read the inputs y and z from memory ‣ check the types of y and z and choose the action ‣ unbox y and z ‣ execute the action ‣ box the output x ‣ write the output x to memory
  104. 104. Further Optimization 1 Automatic Inlining original codefunction getPop(city) { return popdata[city.id];}for (var i = 0; i < N; ++i) { total += getPop(city);}
  105. 105. Further Optimization 1 Automatic Inlining original code JIT compiles as iffunction getPop(city) { you wrote this return popdata[city.id];} for (var i = 0; i < N; ++i) { total += popdata[city.id];for (var i = 0; i < N; ++i) { } total += getPop(city);}
  106. 106. Further Optimization 2 Loop Invariant Code Motion (LICM, “hoisting”) original codefor (var i = 0; i < N; ++i) { total += a[i] * (1 + options.tax);}
  107. 107. Further Optimization 2 Loop Invariant Code Motion (LICM, “hoisting”) original code JIT compiles as if you wrote thisfor (var i = 0; i < N; ++i) { var f = 1 + options.tax; total += a[i] * for (var i = 0; i < N; ++i) { (1 + options.tax); total += a[i] * f;} }
  108. 108. Optimize Only Hot Code
  109. 109. Optimize Only Hot Code• Type-specializing JITs can have a hefty startup cost • Need to collect the type information • Advanced compiler optimizations take longer to run
  110. 110. Optimize Only Hot Code• Type-specializing JITs can have a hefty startup cost • Need to collect the type information • Advanced compiler optimizations take longer to run• Therefore, type specialization is applied selectively • Only on hot code • Tracemonkey: hot = 70 iterations • Crankshaft: hot = according to a profiler • Only if judged to be worthwhile (incomprehensible heuristics)
  111. 111. Current Limitations
  112. 112. Current Limitations• What happens if the types change after compiling? • Just a few changes -> recompile, slight slowdown • Many changes -> give up and deoptimize to basic JIT
  113. 113. Current Limitations• What happens if the types change after compiling? • Just a few changes -> recompile, slight slowdown • Many changes -> give up and deoptimize to basic JIT• Array elements, object properties, and closed-over variables • Usually still boxed • Still need to check type and unbox on get, box on set • Typed arrays might help, but support is not always there yet
  114. 114. Current Limitations• What happens if the types change after compiling? • Just a few changes -> recompile, slight slowdown • Many changes -> give up and deoptimize to basic JIT• Array elements, object properties, and closed-over variables • Usually still boxed • Still need to check type and unbox on get, box on set • Typed arrays might help, but support is not always there yet• JS semantics require overflow checks for integer math
  115. 115. Type Inference for JITs Current Research @Mozilla
  116. 116. Type Inference
  117. 117. Type Inference• Trying to get rid of the last few instances of boxing (from before: array and object properties)
  118. 118. Type Inference• Trying to get rid of the last few instances of boxing (from before: array and object properties)• Idea: use static program analysis to prove types • of object props, array elements, called functions • or, almost prove types, and also prove minimal checks needed
  119. 119. Type Inference Example var a = []; for (var i = 0; i < N; ++i) { a[i] = i * i; ] var sum = 0; for (var i = 0; i < N; ++i) { sum += a[i]; }Type inference gets this...
  120. 120. Type Inference Example var a = []; for (var i = 0; i < N; ++i) { a[i] = i * i; ] var sum = 0; for (var i = 0; i < N; ++i) { sum += a[i]; }Type inference gets this... “i is always a number, so i * i is always a number, so a[_] is always a number!”
  121. 121. Type Inference Example var a = []; var a = []; for (var i = 0; i < N; ++i) { for (var i = 0; i < N; ++i) { a[i] = i * i; if (i % 2) ] a[i] = i * i; else var sum = 0; a[i] = “foo”; for (var i = 0; i < N; ++i) { ] sum += a[i]; } var sum = 0; for (var i = 0; i < N; ++i) { if (i % 2)Type inference gets this... sum += a[i]; } “i is always a number, so i * i is always a number, ...but not this. so a[_] is always a number!”
  122. 122. Type-stable JavaScript The key to running faster in future JITs is type-stable JavaScript. This means JavaScript where you coulddeclare a single engine-internal type for each variable.
  123. 123. Type-stable JS: examples Type-stablevar 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;
  124. 124. Type-stable JS: examples Type-stable NOT type-stablevar g = 34; var g = 34;var o1 = { a: 56 }; var o1 = { a: 56 };var o2 = { a: 99 }; var o2 = { z: 22, a: 56 };for (var i = 0; i < 10; ++i) { for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; var o = i % 2 ? o1 : o2; g += o.a; g += o.a;} }g = 0; g = “hello”;
  125. 125. Type-stable JS: examples Type-stable NOT type-stablevar g = 34; var g = 34;var o1 = { a: 56 }; var o1 = { a: 56 };var o2 = { a: 99 }; var o2 = { z: 22, a: 56 };for (var i = 0; i < 10; ++i) { for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; var o = i % 2 ? o1 : o2; g += o.a; g += o.a; Different shapes} }g = 0; g = “hello”;
  126. 126. Type-stable JS: examples Type-stable NOT type-stablevar g = 34; var g = 34;var o1 = { a: 56 }; var o1 = { a: 56 };var o2 = { a: 99 }; var o2 = { z: 22, a: 56 };for (var i = 0; i < 10; ++i) { for (var i = 0; i < 10; ++i) { var o = i % 2 ? o1 : o2; var o = i % 2 ? o1 : o2; g += o.a; g += o.a; Different shapes} }g = 0; g = “hello”; Type change
  127. 127. Garbage Collection
  128. 128. What Allocates Memory? Objectsnew Object();new MyConstructor();{ a: 4, b: 5 }Object.create(); Arraysnew Array();[ 1, 2, 3, 4 ]; Stringsnew String(“hello”);“<p>” + e.innerHTML + “</p>”
  129. 129. What Allocates Memory? Objects Function Objectsnew Object(); var x = function () { ... }new MyConstructor(); new Function(code);{ a: 4, b: 5 }Object.create(); Arraysnew Array();[ 1, 2, 3, 4 ]; Stringsnew String(“hello”);“<p>” + e.innerHTML + “</p>”
  130. 130. What Allocates Memory? Objects Function Objectsnew Object(); var x = function () { ... }new MyConstructor(); new Function(code);{ a: 4, b: 5 }Object.create(); Arrays Closure Environmentsnew Array(); function outer(name) {[ 1, 2, 3, 4 ]; var x = name; return function inner() { return “Hi, “ + name; Strings } }new String(“hello”);“<p>” + e.innerHTML + “</p>”
  131. 131. What Allocates Memory? Objects Function Objectsnew Object(); var x = function () { ... }new MyConstructor(); new Function(code);{ a: 4, b: 5 }Object.create(); Arrays Closure Environmentsnew Array(); function outer(name) {[ 1, 2, 3, 4 ]; var x = name; return function inner() { return “Hi, “ + name; Strings } }new String(“hello”); name is stored in an“<p>” + e.innerHTML + “</p>” implicitly created object!
  132. 132. GC Pauses Your Program!Time JavaScript GC Running Running JS Paused
  133. 133. GC Pauses Your Program!Time JavaScript GC Running Running JS Paused • Basic GC algorithm (mark and sweep) • Traverse all reachable objects (from locals, window, DOM) • Recycle objects that are not reachable
  134. 134. GC Pauses Your Program!Time JavaScript GC Running Running JS Paused • Basic GC algorithm (mark and sweep) • Traverse all reachable objects (from locals, window, DOM) • Recycle objects that are not reachable • The JS program is paused during GC for safe traversal
  135. 135. GC Pauses Your Program!Time JavaScript GC Running Running JS Paused • Basic GC algorithm (mark and sweep) • Traverse all reachable objects (from locals, window, DOM) • Recycle objects that are not reachable • The JS program is paused during GC for safe traversal • Pauses may be long: 100 ms or more • Serious problem for animation • Can also be a drag on general performance
  136. 136. Reducing Pauses with Science 1 Generational GC Chrome
  137. 137. Reducing Pauses with Science 1 Generational GC Chrome Idea: Optimize for creating many short-lived objects
  138. 138. Reducing Pauses with Science 1 Generational GC Chrome Idea: Optimize for creating many short-lived objects Create objects in a frequently collected nursery area
  139. 139. Reducing Pauses with Science 1 Generational GC Chrome 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
  140. 140. Reducing Pauses with Science 1 Generational GC Chrome 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 JavaScript GC RunningSimple GC Running JS Paused
  141. 141. Reducing Pauses with Science 1 Generational GC Chrome 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 JavaScript GC Running Simple GC Running JS Paused JavaScriptGenerational GC Running
  142. 142. Reducing Pauses with Science 1 Generational GC Chrome 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 JavaScript GC Running Simple GC Running JS Paused JavaScriptGenerational GC Running nursery collection (<100 us)
  143. 143. Reducing Pauses with Science 1 Generational GC Chrome 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 JavaScript GC Running Simple GC Running JS Paused JavaScriptGenerational GC Running tenured collection nursery collection (<100 us)
  144. 144. Reducing Pauses with Science 1 Generational GC Chrome 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 JavaScript GC Running Simple GC Running JS Paused JavaScriptGenerational GC fewer pauses! Running tenured collection nursery collection (<100 us)
  145. 145. Generational GC by Examplescavenging young generation (aka nursery)mark-and-sweep tenured generation Message Message Array
  146. 146. Generational GC by Examplescavenging young generation (aka nursery) Pointmark-and-sweep tenured generation Message Message Array
  147. 147. Generational GC by Examplescavenging young generation (aka nursery) Point Pointmark-and-sweep tenured generation Message Message Array
  148. 148. Generational GC by Examplescavenging young generation (aka nursery) Point Point Linemark-and-sweep tenured generation Message Message Array
  149. 149. Generational GC by Examplescavenging young generation (aka nursery) Point Point Line a bmark-and-sweep tenured generation Message Message Array
  150. 150. Generational GC by Examplescavenging young generation (aka nursery) Point Point Line Point a bmark-and-sweep tenured generation Message Message Array
  151. 151. Generational GC by Examplescavenging young generation (aka nursery) Point Point Line Point Message a bmark-and-sweep tenured generation Message Message Array
  152. 152. Generational GC by Examplescavenging young generation (aka nursery) Point Point Line Point Message a bmark-and-sweep tenured generation Message Message Array
  153. 153. Generational GC by Examplescavenging young generation (aka nursery) Point Point Line Point Message Point a bmark-and-sweep tenured generation Message Message Array
  154. 154. Generational GC by Examplescavenging young generation (aka nursery) Point Point Line Point Point a bmark-and-sweep tenured generation Message Message Message Array
  155. 155. Generational GC by Examplescavenging young generation (aka nursery)mark-and-sweep tenured generation Message Message Message Array
  156. 156. Reducing Pauses with Science 1I Current Incremental GC Research @Mozilla
  157. 157. Reducing Pauses with Science 1I Current Incremental GC Research @Mozilla Idea: Do a little bit of GC traversal at a time
  158. 158. Reducing Pauses with Science 1I Current Incremental GC Research @Mozilla Idea: Do a little bit of GC traversal at a time JavaScript GC RunningSimple GC Running JS Paused
  159. 159. Reducing Pauses with Science 1I Current Incremental GC Research @Mozilla Idea: Do a little bit of GC traversal at a time JavaScript GC Running Simple GC Running JS PausedIncremental GC
  160. 160. Reducing Pauses with Science 1I Current Incremental GC Research @Mozilla Idea: Do a little bit of GC traversal at a time JavaScript GC Running Simple GC Running JS PausedIncremental GC shorter pauses!
  161. 161. Reducing Pauses in Practice
  162. 162. Reducing Pauses in Practice• For all GCs • Fewer live objects -> shorter pauses (if not incremental), less time spent in GC
  163. 163. Reducing Pauses in Practice• For all GCs • Fewer live objects -> shorter pauses (if not incremental), less time spent in GC• For simple GCs • Lower allocation rate (objects/second) -> less frequent pauses
  164. 164. Reducing Pauses in Practice• For all GCs • Fewer live objects -> shorter pauses (if not incremental), less time spent in GC• For simple GCs • Lower allocation rate (objects/second) -> less frequent pauses• For generational GCs • Short-lived objects don’t affect pause frequency • Long-lived objects cost extra (promotion = copying)
  165. 165. JavaScript Engines in Practice
  166. 166. Performance Faults• Performance fault: when a tiny change hurts performance • Sometimes, just makes one statement slower • Other times, deoptimizes the entire function!• Reasons we have performance faults • bug, tends to get quickly • “rare” case, will get fixed if not rare • hard to optimize, RSN...
  167. 167. Strings
  168. 168. Strings• In the Slow Zone, but some things are faster than you might think
  169. 169. Strings• In the Slow Zone, but some things are faster than you might think• .substring() is fast, O(1) • Don’t need to copy characters, just point within original
  170. 170. Strings• In the Slow Zone, but some things are faster than you might think• .substring() is fast, O(1) • Don’t need to copy characters, just point within original• Concatenation is also optimized • Batch up inputs in a rope or concat tree, concat all at once • Performance fault: prepending (Chrome, Opera)
  171. 171. Strings• In the Slow Zone, but some things are faster than you might think• .substring() is fast, O(1) // Prepending example var s = “”; •Don’t need to copy characters, just point iwithin<original { for (var = 0; i 100; ++i) s = i + s;• Concatenation is also optimized } • Batch up inputs in a rope or concat tree, concat all at once • Performance fault: prepending (Chrome, Opera)
  172. 172. Arrays fast: dense arrayvar a = []; Want a fast array?for (var i = 0; i < 100; ++i) { a[i] = 0; ‣ Make sure it’s dense} ‣ 0..N fill or push fill is always dense 3-15x slower: sparse array ‣ Huge gaps are always sparsevar a = []; ‣ N..0 fill is sparse on Firefoxa[10000] = 0;for (var i = 0; i < 100; ++i) { a[i] = 0; ‣ adding a named property is sparse on Firefox, IE}a.x = 7; // Fx, IE only
  173. 173. Iteration over Arraysfastest: index iteration// This runs in all in JIT code,// so it’s really fast.for (var i = 0; i < a.length; ++i) { sum += a[i];}
  174. 174. Iteration over Arrays 3-15x slower: functional style // This makes N function calls,fastest: index iteration // and most JITs don’t optimize // through C++ reduce(). sum = a.reduce(function(a, b) {// This runs in all in JIT code, return a + b; });// so it’s really fast.for (var i = 0; i < a.length; ++i) { sum += a[i];} 20-80x slower: for-in // This calls a C++ function to // navigate the property list. for (var i in a) { sum += a[i]; }
  175. 175. Functions• Function calls use ICs, so they are fast • Manual inlining can still help sometimes• Key performance faults: • f.call() - 1.3-35x slower than f() • f.apply() - 5-50x slower than f() • arguments - often very slow, but varies
  176. 176. Creating Objects Creating objects is slowDoesn’t matter too much how you create or populate
  177. 177. Creating Objects Creating objects is slowDoesn’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);
  178. 178. OOP Styling
  179. 179. OOP Styling Prototypefunction Point(x, y) { this.x = x; this.y = y;}Point.prototype = { distance: function(pt2) ...
  180. 180. OOP Styling Prototype Information-Hidingfunction Point(x, y) { this.x = x; function Point(x, y) { this.y = y; return {} distance: function(pt2) ...Point.prototype = { } distance: function(pt2) ... }
  181. 181. OOP Styling Prototype Information-Hidingfunction Point(x, y) { this.x = x; function Point(x, y) { this.y = y; return {} distance: function(pt2) ...Point.prototype = { } distance: function(pt2) ... } Instance Methods function Point(x, y) { this.x = x; this.y = y; this.distance = function(pt2) ... }
  182. 182. OOP Styling Prototype Information-Hidingfunction Point(x, y) { this.x = x; function Point(x, y) { this.y = y; return {} distance: function(pt2) ...Point.prototype = { } distance: function(pt2) ... }Prototype style is much faster to create Instance Methods(each closure creates a function object) function Point(x, y) { this.x = x; this.y = y; this.distance = function(pt2) ... }
  183. 183. OOP Styling Prototype Information-Hidingfunction Point(x, y) { this.x = x; function Point(x, y) { this.y = y; return {} distance: function(pt2) ...Point.prototype = { } distance: function(pt2) ... }Prototype style is much faster to create Instance Methods(each closure creates a function object) function Point(x, y) { this.x = x; this.y = y; this.distance = function(pt2) ... }Using the objects is about the same
  184. 184. Exceptions• Exceptions assumed to be rare in perf-sensitive code • running a try statement is free on most browers • throw/catch is really slow• There are many performance faults around exceptions • just having a try statement deoptimizes on some browers • try-finally is perf fault on some
  185. 185. eval and with Short version: Do not use anywhere near performance sensitive code! Mind-Bogglingly Awful Still Terrible5-100x slower than using a function call 2-10x slower than without evalvar sum = 0; var sum = 0;for (var i = 0; i < N; ++i) { eval(“”); sum = eval(“sum + i”); for (var i = 0; i < N; ++i) {} sum = eval(“sum + i”); }
  186. 186. Top 5 Things to Know
  187. 187. Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code
  188. 188. Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code4. Avoid creating objects in hot loops
  189. 189. Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code4. Avoid creating objects in hot loops3. Use dense arrays (know what causes sparseness)
  190. 190. Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code4. Avoid creating objects in hot loops3. Use dense arrays (know what causes sparseness)2. Write type-stable code
  191. 191. Top 5 Things to Know5. Avoid eval, with, exceptions near perf-senstive code4. Avoid creating objects in hot loops3. Use dense arrays (know what causes sparseness)2. Write type-stable code1. ...
  192. 192. Talk To UsJS engine developers want to help you. Tell us about: • Performance faults you run into • Exciting apps that require fast JS • Anything interesting you discover about JS performance

×