Slide 1

Slide 1 text

Supersonic JavaScript @ariyahidayat

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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)

Slide 4

Slide 4 text

Beyond checklists Global maximum

Slide 5

Slide 5 text

Short Function

Slide 6

Slide 6 text

Function = Expensive sortDepartment totalDepartementExpense totalEmployeesSalaries getEmployeeData OLD Wisdom

Slide 7

Slide 7 text

NEW movement Let the JavaScript engine figure out the best way to execute the functions.

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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.

Slide 11

Slide 11 text

Fixed Object Shape

Slide 12

Slide 12 text

WILD idea How to avoid any deoptimization in the JavaScript engine?

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

(Optimized) Property Access console.log(car.color); Execute the generic property access Shape check Get the value from property #1 color speed

Slide 15

Slide 15 text

“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

Slide 16

Slide 16 text

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();

Slide 17

Slide 17 text

Garbage Handling

Slide 18

Slide 18 text

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; }

Slide 19

Slide 19 text

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()

Slide 20

Slide 20 text

Memory Profiling https://developer.chrome.com/devtools/docs/javascript-memory-profiling

Slide 21

Slide 21 text

Performance Analysis

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

Profile Guided

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Algorithmic Complexity

Slide 29

Slide 29 text

Fast = Enough? Alice Bob Chuck Dan ... Bob Alice Dan Chuck ... Sort How’s the speed? 2 ms to sort 10 contacts

Slide 30

Slide 30 text

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 ???

Slide 31

Slide 31 text

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; }

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Final Words

Slide 34

Slide 34 text

tools and knowledge not rules and checklists

Slide 35

Slide 35 text

contextual profiling not microbenchmarks

Slide 36

Slide 36 text

T D D B D D

Slide 37

Slide 37 text

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