Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Supersonic JS

Supersonic JS

Presented at O'Reilly Velocity 2015 in Santa Clara: http://velocityconf.com/devops-web-performance-2015/public/schedule/detail/42098

Analyzing the performance of large-scale JavaScript applications requires a distinct set of tools. It is no longer enough to run various benchmarks by creating loops and measuring the elapsed time. The amazing progress of modern JavaScript engines means that developers should not stress about outdated considerations such as cache array length, avoiding ‘switch’ statements, and using ‘while’ instead of ‘for.’ Understanding the inner workings of the engine itself will reveal the typical code patterns favored for maximum execution speed (short function, fixed object shape, profile-guided, garbage minimization). We will also cover the use of strategies like sampling and tracing, in order to spot performance issues while simultaneously avoiding being trapped in a local maxima.

Ariya Hidayat

May 29, 2015
Tweet

More Decks by Ariya Hidayat

Other Decks in Programming

Transcript

  1. The real problem is that programmers have spent far too

    much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming. Computer Programming as an Art Knuth’s Turing Award lecture (1974)
  2. Automatic Inlining function square(p) { return p * p; }

    function f(x) { var sum = 0; for (var i = 0; i < x; i++) sum += square(i); return sum; } function f(x) { var sum = 0; for (var i = 0; i < x; i++) sum += i * i; return sum; } http://ariya.ofilabs.com/2013/04/automatic-inlining-in-javascript-engines.html
  3. Deferred Parsing To further reduce the time to first executed

    instruction, Chakra processes and emits bytecode only for functions that are about to be executed using a mechanism called deferred parsing. http://blogs.msdn.com/b/ie/archive/2012/06/13/advances-in-javascript-performance-in-ie10-and-windows-8.aspx
  4. Lazy Parsing http://ariya.ofilabs.com/2012/07/lazy-parsing-in-javascript-engines.html function add(x, y) { return x +

    y; } function mul(x, y) { return x * y; } alert(add(40, 2)); Declare a function call add with the function body “{ return x + y; }”. Declare a function call mul with the function body “{ return x * y; }”. Call alert with the result of function add with 40 and 2 as the arguments. 1 2 Call function add. Hmm, it is not parsed yet. Call the real parser for “{ return x + y; }”. It accepts x and y as the arguments. The return value is a binary operation + of x and y.
  5. Shape Transition function Vehicle() { this.color = 'white'; this.speed =

    0; } var car = new Vehicle(); car.color = 'black'; car.maker = 'BMW'; var motorbike = new Vehicle(); motorbike.wheels = ['front', 'back']; color speed color speed maker color speed wheels
  6. “Freeze” the Object Shape var universe = { answer: 42

    }; // do something else universe.panic = false; var universe = { answer: 42, panic: true }; // do something else universe.panic = false; http://ariya.ofilabs.com/2012/02/javascript-object-structure-speed-matters.html
  7. Avoid Conditional Transition var car = { color: 'blue' };

    if (currentYear > 2015) car.backupCamera = new Camera(); var car = { color: 'blue', backupCamera: null }; if (currentYear > 2015) car.backupCamera = new Camera();
  8. Minimize Object Construction https://www.youtube.com/watch?v=Vo72W1HWeFI var tick = new Date(); for

    (var i = 0, j = 0; i < 4e4; ++i){ var delta = new Date(); delta = delta - tick; tick = new Date(); j += delta; } var tick = Date.now(); for (var i = 0, j = 0; i < 4e4; ++i) { var delta = Date.now() - tick; tick = Date.now(); j += delta; }
  9. GC Tracing on 56 ms: Scavenge 1.8 (36.0) -> 0.9

    (36.0) MB, 2.8 ms 73 ms: Scavenge 1.8 (36.0) -> 0.9 (37.0) MB, 2.8 ms 89 ms: Scavenge 1.9 (37.0) -> 0.9 (37.0) MB, 1.0 ms 109 ms: Scavenge 1.9 (37.0) -> 0.9 (37.0) MB, 1.0 ms 126 ms: Scavenge 1.9 (37.0) -> 0.9 (37.0) MB, 0.9 ms 141 ms: Scavenge 1.9 (37.0) -> 0.9 (37.0) MB, 0.9 ms 159 ms: Scavenge 1.9 (37.0) -> 0.9 (37.0) MB, 0.9 ms 176 ms: Scavenge 1.9 (37.0) -> 0.9 (37.0) MB, 1.0 ms 192 ms: Scavenge 1.9 (37.0) -> 0.9 (37.0) MB, 0.9 ms 207 ms: Scavenge 1.9 (37.0) -> 0.9 (37.0) MB, 1.0 ms 54 ms: Scavenge 1.8 (36.0) -> 0.9 (36.0) MB, 2.9 ms 67 ms: Scavenge 1.8 (36.0) -> 0.9 (37.0) MB, 2.7 ms new Date( ) Date.now()
  10. Timing Prepare the stopwatch Mark the start and the end

    Sampling Periodically check which function is being executed Tracing Track all function calls and exits http://ariya.ofilabs.com/2012/12/javascript-performance-analysis-sampling-tracing-and-timing.html
  11. function isDigit(ch) { return (ch !== ' ') && '0123456789'.indexOf(ch)

    >= 0; } Fast Lane http://ariya.ofilabs.com/2013/07/profile-guided-javascript-optimization.html function isDigit(ch) { return '0123456789'.indexOf(ch) >= 0; } Shortcut
  12. Object in a Set var valid_words = { 'foobar': true,

    'bar': true, 'baz': true, 'quux': true }; function is_valid(word) { return valid_words.hasOwnProperty(word); } is_valid('fox'); // false http://ariya.ofilabs.com/2012/08/determining-objects-in-a-set-examples-in-javascript.html Dictionary Spell checker
  13. Tiered Conditionals http://ariya.ofilabs.com/2012/08/determining-objects-in-a-set-examples-in-javascript.html function is_valid(word) { switch (word.length) { case

    3: return word === 'bar' || word === 'baz'; case 4: return word === 'quux'; case 6: return word === 'foobar'; } return false; } Filter #1: length
  14. Fast = Enough? Alice Bob Chuck Dan ... Bob Alice

    Dan Chuck ... Sort How’s the speed? 2 ms to sort 10 contacts
  15. Array.prototype.swap = function (i, j) { var k = this[i];

    this[i] = this[j]; this[j] = k; } function sort(list) { var items = list.slice(0), swapped = false, p, q; for (p = 1; p < items.length; ++p) { for (q = 0; q < items.length - p; ++q) { if (items[q + 1] < items[q]) { items.swap(q, q + 1); swapped =true; } } if (!swapped) break; } return items; } Bubble Sort ???
  16. Run-time Complexity http://ariya.ofilabs.com/2012/01/scalable-web-apps-the-complexity-issue.html Array.prototype.swap = function (i, j) { var

    k = this[i]; this[i] = this[j]; this[j] = k; } Array.prototype.swap = function (i, j) { Log({ name: 'Array.prototype.swap', lineNumber: 1, range: [23, 94] }); var k = this[i]; this[i] = this[j]; this[j] = k; }