Supersonic JavaScript

Supersonic JavaScript

Presented at Samsung Web Tech Talk: http://www.meetup.com/Samsung-Web-Tech-Talk/events/171219722/

Writing fast JavaScript code is not only about running loops, measuring the elapsed time, and getting obsessed with microbenchmarks. Understanding the inner workings of the JavaScript engine will reveal the typical code patterns favored for maximum execution speed (short function, fixed object shape, profile-guided, garbage minimization).

0284b8950e0f4a57bcc092d4dbb98d97?s=128

Ariya Hidayat

April 07, 2014
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. Performance Analysis 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
  5. Status Quo?

  6. Short Function

  7. Function = Expensive sortDepartment totalDepartementExpense totalEmployeesSalaries getEmployeeData OLD Wisdom

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

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

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

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

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

  19. None
  20. 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
  21. 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
  22. 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
  23. Garbage Handling

  24. 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; }
  25. 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()
  26. Final Words

  27. Summary Measure twice, cut once Under the hood: explore and

    learn Be advised of every best practice
  28. Thank You shapesecurity.com @ariyahidayat