javascript performance patterns

69
JavaScript Performance Patterns @stoyanstefanov frontendconf.ch Sept 6, 2012

Upload: stoyan-stefanov

Post on 06-May-2015

9.016 views

Category:

Technology


1 download

DESCRIPTION

http://www.frontendconf.ch/speakers/#speaker-6

TRANSCRIPT

Page 1: JavaScript performance patterns

JavaScript Performance Patterns

@stoyanstefanovfrontendconf.ch

Sept 6, 2012

Page 2: JavaScript performance patterns

JavaScript Performance Patterns

Page 3: JavaScript performance patterns

Importance of Performance

http://bookofspeed.com

Page 4: JavaScript performance patterns

Importance of JavaScript Performance

http://httparchive.org

Page 5: JavaScript performance patterns

// todo

1. Loading JavaScript2. Runtime / UI / DOM

+ benchmarks+ shims

Page 6: JavaScript performance patterns
Page 7: JavaScript performance patterns
Page 8: JavaScript performance patterns

Loading

Page 9: JavaScript performance patterns

First things first

• reduce # of script files• gzip, shave 70% off• minify, extra 40-50%• Expires headers• CDN

http://yslow.orgPageSpeed

http://webpagetest.org

Page 10: JavaScript performance patterns

<script src="http://…">

NOPE!

Page 11: JavaScript performance patterns

SPOF

• Single point of failure• JS blocks

http://phpied.com/3po-failSPOF-O-Matic:

https://chrome.google.com/webstore/detail/plikhggfbplemddobondkeogomgoodeg

Page 12: JavaScript performance patterns

Off the critical path

Page 13: JavaScript performance patterns

Asynchronous JS

• <script defer>• <script async>• until then…

Page 14: JavaScript performance patterns

Dynamic script node

var js = document.createElement('script');js.src = 'http://cdn.com/my.js';document.getElementsByTagName('head')[0].appendChild(js);

http://calendar.perfplanet.com/2011/the-art-and-craft-of-the-async-snippet/

Page 15: JavaScript performance patterns

But…, butt…, button?

Q: <button onclick="…"?A: To hell with it

Q: Dependencies?A: onload event and js.onreadystatechange

load('jquery.js', 'mystuff.js', function () { mystuff.go();});

Page 16: JavaScript performance patterns

Unblocking onload

• Async JS blocks window.onload in !IE• May or may not be a problem• There's a solution: FIF

Page 17: JavaScript performance patterns

<fif>

frame-in-frame aka friendly frames aka this Meebo thing

Page 18: JavaScript performance patterns

FIF

1) createiframe src="js:false"

2) in the frame doc.write a <body onload …

3) …that loads JS

Page 19: JavaScript performance patterns

FIF (snippet)var iframe = document.createElement('iframe');document.body.appendChild(iframe);var doc = iframe.contentWindow.document;doc.open().write('<body onload="'+ 'var js = document.createElement(\'script\');'+ 'js.src = \'http://example.org/js.js\';'+ 'document.body.appendChild(js);">');doc.close();

Page 20: JavaScript performance patterns

FIF

• unblocks onload, but…• more complex• requires JS changes

Page 21: JavaScript performance patterns

your script (before)

// fun with window // and document

Page 22: JavaScript performance patterns

your script (before)

(function() {

// fun with window // and document}());

Page 23: JavaScript performance patterns

FIF (after)

(function(window) { var document = window.document; // fun with window // and document}(parent.window));

Page 24: JavaScript performance patterns

FIF in the wild

• experimental support in FB JS SDK• http://jsbin.com/axibow/1/edit

Page 25: JavaScript performance patterns

</fif>

Page 26: JavaScript performance patterns

Load JS but not execute

• Use cases:– preload in anticipation– lazy

Page 27: JavaScript performance patterns

Preload, then eventually execute

1. fetch the script, but don’t run it2. run it at some point (same as async JS)

Page 28: JavaScript performance patterns

Fetching

• IE: dynamic script node, not in the DOM• All others: CORS (XHR2)– your CDN should let you specifyAccess-Control-Allow-Origin header or else!

Page 29: JavaScript performance patterns

Preload, then execute// preloadvar js = document.createElement('script');if (!js.readyState || js.readyState !== 'uninitialized') { // non IE var xhr = new XMLHttpRequest(); if ('withCredentials' in xhr) { // XHR2 xhr.open('GET', url, false); xhr.send(null); }}js.src = url; // IE preloads! Thanks @getify

// executedocument.getElementsByTagName('head')[0].appendChild(js);

Page 30: JavaScript performance patterns

// todo

1. Loading JavaScript2. Runtime / UI / DOM

+ benchmarks+ shims

Page 31: JavaScript performance patterns

Benchmarks

• Lies, damn lies and performance advice• Test the wrong thing• Measure the wrong thing• Even if not, still draw the wrong conclusions

Page 32: JavaScript performance patterns

Your first benchmark

var start = new Date();// loop 100000 timesvar took = new Date() – start;

NOPE!

Page 33: JavaScript performance patterns

Benchmark.js

• by John-David Dalton• used in http://jsperf.com – calibrating the test– end time (ops/second)– statistical significance– margin of error

Page 35: JavaScript performance patterns

Benchmarking browsers?

No, thanks

Page 36: JavaScript performance patterns

Let's test!

Page 37: JavaScript performance patterns

String concat

var text = "";text += "moar";

vs.

var parts = [];parts.push('moar');var text = push.join('');

http://jsperf.com/join-concat/

Page 38: JavaScript performance patterns

String concat

Page 39: JavaScript performance patterns

The pen is mightier than the sword! *

* Only if the sword is very small and the pen very sharp

Page 40: JavaScript performance patterns

"Don't A, B is so much faster!"

You should check it again

Page 41: JavaScript performance patterns

Profiling

Page 42: JavaScript performance patterns
Page 43: JavaScript performance patterns
Page 44: JavaScript performance patterns
Page 45: JavaScript performance patterns

Picking battles

Page 46: JavaScript performance patterns

DOM

Page 47: JavaScript performance patterns

DOM

• DOM is slow• How slow?• http://jsperf.com/touching/4

Page 48: JavaScript performance patterns

DOM

// DOMdiv.innerHTML += 'a';div.innerHTML += 'b';

// stringvar html = '';html += 'a';html += 'b';div.innerHTML = html;

Page 49: JavaScript performance patterns

DOM

Page 50: JavaScript performance patterns

DOM + string concat

• put things in perspective http://jsperf.com/touching/5

Page 51: JavaScript performance patterns

DOMlandECMAland

Page 52: JavaScript performance patterns

DOM

• caching DOM references• caching length in collection loops• "offline" changes in document fragment• batch style changes• reducing reflows and repaints

Page 53: JavaScript performance patterns

reflows

bodystyle.color = 'red';tmp = computed.backgroundColor;bodystyle.color = 'white';tmp = computed.backgroundImage;bodystyle.color = 'green';tmp = computed.backgroundAttachment;

bodystyle.color = 'red';bodystyle.color = 'white';bodystyle.color = 'green';tmp = computed.backgroundColor;tmp = computed.backgroundImage;tmp = computed.backgroundAttachment;

getComputedStyle(), or currentStyle in IE

Page 54: JavaScript performance patterns

data attributes

<div data-stuff="convenient"></div>

• div.dataset.stuff• div.getAttribute('data-stuff')• Data.get(div).stuff // DIY

Page 55: JavaScript performance patterns

data attributes DIYvar Data = function() { var warehouse = {}; var count = 1; return { set: function (dom, data) { if (!dom.__data) { dom.__data = "hello" + count++; } warehouse[dom.__data] = data; }, get: function(dom) { return warehouse[dom.__data]; } };}();

Page 56: JavaScript performance patterns

data attributes

Page 57: JavaScript performance patterns

data attributeshttp://jsperf.com/data-dataset

5-20 times slower

Page 58: JavaScript performance patterns

Shims and polyfills

Page 59: JavaScript performance patterns

Shims

• pick the smaller/optimized one• one that uses native where available *• load conditionally

e.g. JSON is non-native only for 8% of users *, why load shim 100% of the time

* http://html5please.us

Page 60: JavaScript performance patterns

Fast ECMAScript5 natives?

• JDD: "browsers optimize loops because of benchmarks"

• http://jsperf.com/native-for-loop-vs-array-foreach-and-array-map-vs-lodas/2

Page 61: JavaScript performance patterns

jQuery: the most popular polyfill

• not free (perf-wise)• do you need it?

Page 62: JavaScript performance patterns

Cost of parsing and evaluatinghttp://calendar.perfplanet.com/2011/lazy-evaluation-of-commonjs-modules/

Page 63: JavaScript performance patterns

Cost of parsing and evaluating

Page 64: JavaScript performance patterns

Experiment: jQuery vs. Zepto

What’s the cost of just dropping it on the page?

Page 65: JavaScript performance patterns

jsperf.com/zepto-jq-eval

[…]

Page 66: JavaScript performance patterns

jsperf.com/zepto-jq-eval

Page 67: JavaScript performance patterns

jsperf.com/zepto-jq-eval

z: 56 times faster on iPhone 4

Page 68: JavaScript performance patterns

In closure…

• JS off the critical path (async, lazy, preload)

• Practice writing jsperf.com tests ("jsperf URL or it didn't happen!")

• Don't touch the DOM (remember the bridge)• Use the tools (Timeline, CPU/heap profiler,

SpeedTracer, Dynatrace)• Think of poor mobile

(easy with the shims)

Page 69: JavaScript performance patterns

Thank you!

http://slideshare.net/stoyan/