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.

0284b8950e0f4a57bcc092d4dbb98d97?s=128

Ariya Hidayat

May 29, 2015
Tweet

Transcript

  1. Supersonic JavaScript @ariyahidayat

  2. First Things First, Steven Covey “The Big Rock” http://calendar.perfplanet.com/2013/javascript-performance-big-picture/

  3. 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)
  4. Beyond checklists Global maximum

  5. Short Function

  6. Function = Expensive sortDepartment totalDepartementExpense totalEmployeesSalaries getEmployeeData OLD Wisdom

  7. NEW movement Let the JavaScript engine figure out the best

    way to execute the functions.
  8. 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
  9. 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
  10. 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.
  11. Fixed Object Shape

  12. WILD idea How to avoid any deoptimization in the JavaScript

    engine?
  13. 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
  14. (Optimized) Property Access console.log(car.color); Execute the generic property access Shape

    check Get the value from property #1 color speed
  15. “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
  16. 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();
  17. Garbage Handling

  18. 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; }
  19. 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()
  20. Memory Profiling https://developer.chrome.com/devtools/docs/javascript-memory-profiling

  21. Performance Analysis

  22. 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
  23. Profile Guided

  24. None
  25. 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
  26. 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
  27. 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
  28. Algorithmic Complexity

  29. Fast = Enough? Alice Bob Chuck Dan ... Bob Alice

    Dan Chuck ... Sort How’s the speed? 2 ms to sort 10 contacts
  30. 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 ???
  31. 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; }
  32. None
  33. Final Words

  34. tools and knowledge not rules and checklists

  35. contextual profiling not microbenchmarks

  36. T D D B D D

  37. Thank You! shapesecurity.com @ariyahidayat And don’t forget to rate the

    talk