javascript performance patterns
DESCRIPTION
http://www.frontendconf.ch/speakers/#speaker-6TRANSCRIPT
![Page 1: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/1.jpg)
JavaScript Performance Patterns
@stoyanstefanovfrontendconf.ch
Sept 6, 2012
![Page 2: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/2.jpg)
JavaScript Performance Patterns
![Page 5: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/5.jpg)
// todo
1. Loading JavaScript2. Runtime / UI / DOM
+ benchmarks+ shims
![Page 6: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/6.jpg)
![Page 7: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/7.jpg)
![Page 8: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/8.jpg)
Loading
![Page 9: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/9.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/10.jpg)
<script src="http://…">
NOPE!
![Page 11: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/11.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/12.jpg)
Off the critical path
![Page 13: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/13.jpg)
Asynchronous JS
• <script defer>• <script async>• until then…
![Page 14: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/14.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/15.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/16.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/17.jpg)
<fif>
frame-in-frame aka friendly frames aka this Meebo thing
![Page 18: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/18.jpg)
FIF
1) createiframe src="js:false"
2) in the frame doc.write a <body onload …
3) …that loads JS
![Page 19: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/19.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/20.jpg)
FIF
• unblocks onload, but…• more complex• requires JS changes
![Page 21: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/21.jpg)
your script (before)
// fun with window // and document
![Page 22: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/22.jpg)
your script (before)
(function() {
// fun with window // and document}());
![Page 23: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/23.jpg)
FIF (after)
(function(window) { var document = window.document; // fun with window // and document}(parent.window));
![Page 24: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/24.jpg)
FIF in the wild
• experimental support in FB JS SDK• http://jsbin.com/axibow/1/edit
![Page 25: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/25.jpg)
</fif>
![Page 26: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/26.jpg)
Load JS but not execute
• Use cases:– preload in anticipation– lazy
![Page 27: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/27.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/28.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/29.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/30.jpg)
// todo
1. Loading JavaScript2. Runtime / UI / DOM
+ benchmarks+ shims
![Page 31: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/31.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/32.jpg)
Your first benchmark
var start = new Date();// loop 100000 timesvar took = new Date() – start;
NOPE!
![Page 33: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/33.jpg)
Benchmark.js
• by John-David Dalton• used in http://jsperf.com – calibrating the test– end time (ops/second)– statistical significance– margin of error
![Page 34: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/34.jpg)
http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/
![Page 35: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/35.jpg)
Benchmarking browsers?
No, thanks
![Page 36: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/36.jpg)
Let's test!
![Page 37: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/37.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/38.jpg)
String concat
![Page 39: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/39.jpg)
The pen is mightier than the sword! *
* Only if the sword is very small and the pen very sharp
![Page 40: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/40.jpg)
"Don't A, B is so much faster!"
You should check it again
![Page 41: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/41.jpg)
Profiling
![Page 42: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/42.jpg)
![Page 43: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/43.jpg)
![Page 44: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/44.jpg)
![Page 45: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/45.jpg)
Picking battles
![Page 46: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/46.jpg)
DOM
![Page 48: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/48.jpg)
DOM
// DOMdiv.innerHTML += 'a';div.innerHTML += 'b';
// stringvar html = '';html += 'a';html += 'b';div.innerHTML = html;
![Page 49: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/49.jpg)
DOM
![Page 50: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/50.jpg)
DOM + string concat
• put things in perspective http://jsperf.com/touching/5
![Page 51: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/51.jpg)
DOMlandECMAland
![Page 52: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/52.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/53.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/54.jpg)
data attributes
<div data-stuff="convenient"></div>
• div.dataset.stuff• div.getAttribute('data-stuff')• Data.get(div).stuff // DIY
![Page 55: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/55.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/56.jpg)
data attributes
![Page 58: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/58.jpg)
Shims and polyfills
![Page 59: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/59.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/60.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/61.jpg)
jQuery: the most popular polyfill
• not free (perf-wise)• do you need it?
![Page 62: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/62.jpg)
Cost of parsing and evaluatinghttp://calendar.perfplanet.com/2011/lazy-evaluation-of-commonjs-modules/
![Page 63: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/63.jpg)
Cost of parsing and evaluating
![Page 64: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/64.jpg)
Experiment: jQuery vs. Zepto
What’s the cost of just dropping it on the page?
![Page 65: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/65.jpg)
jsperf.com/zepto-jq-eval
[…]
![Page 66: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/66.jpg)
jsperf.com/zepto-jq-eval
![Page 67: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/67.jpg)
jsperf.com/zepto-jq-eval
z: 56 times faster on iPhone 4
![Page 68: JavaScript performance patterns](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/68.jpg)
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](https://reader035.vdocuments.site/reader035/viewer/2022081514/554a1dbfb4c9055c598b5667/html5/thumbnails/69.jpg)
Thank you!
http://slideshare.net/stoyan/