JavaScript Performance Patterns         @stoyanstefanov         frontendconf.ch           Sept 6, 2012
JavaScript Performance Patterns
Importance of Performance                    http://bookofspeed.com
Importance of JavaScript Performance                         http://httparchive.org
// todo1. Loading JavaScript2. Runtime / UI / DOM   + benchmarks   + shims
Loading
First things first•   reduce # of script files•   gzip, shave 70% off•   minify, extra 40-50%•   Expires headers•   CDN   ...
<script src="http://…">
SPOF• Single point of failure• JS blocks                                                        http://phpied.com/3po-fail...
Off the critical path
Asynchronous JS• <script defer>• <script async>• until then…
Dynamic script nodevar js = document.createElement(script);js.src = http://cdn.com/my.js;document.getElementsByTagName(hea...
But…, butt…, button?Q: <button onclick="…"?A: To hell with itQ: Dependencies?A: onload event and js.onreadystatechangeload...
Unblocking onload• Async JS blocks window.onload in !IE• May or may not be a problem• Theres a solution: FIF
<fif>frame-in-frame aka friendly frames      aka this Meebo thing
FIF1)   create     iframe src="js:false"2)   in the frame doc.write a     <body onload …3)   …that loads JS
FIF (snippet)var iframe = document.createElement(iframe);document.body.appendChild(iframe);var doc = iframe.contentWindow....
FIF• unblocks onload, but…• more complex• requires JS changes
your script (before)// fun with window// and document
your script (before)(function() {  // fun with window  // and document}());
FIF (after)(function(window) {  var document = window.document;  // fun with window  // and document}(parent.window));
FIF in the wild• experimental support in FB JS SDK• http://jsbin.com/axibow/1/edit
</fif>
Load JS but not execute• Use cases:  – preload in anticipation  – lazy
Preload, then eventually execute1. fetch the script, but don’t run it2. run it at some point (same as async JS)
Fetching• IE: dynamic script node, not in the DOM• All others: CORS (XHR2)  – your CDN should let you specify    Access-Co...
Preload, then execute// preloadvar js = document.createElement(script);if (!js.readyState || js.readyState !== uninitializ...
// todo1. Loading JavaScript2. Runtime / UI / DOM   + benchmarks   + shims
Benchmarks•   Lies, damn lies and performance advice•   Test the wrong thing•   Measure the wrong thing•   Even if not, st...
Your first benchmarkvar start = new Date();// loop 100000 timesvar took = new Date() – start;
Benchmark.js• by John-David Dalton• used in http://jsperf.com  – calibrating the test  – end time (ops/second)  – statisti...
http://calendar.perfplanet.com/2010/bulletpro                     of-javascript-benchmarks/
Benchmarking browsers?       No, thanks
Lets test!
String concatvar text = "";text += "moar";vs.var parts = [];parts.push(moar);var text = push.join();                      ...
String concat
The pen is mightier than the sword! ** Only if the sword is very small and the pen very sharp
"Dont A, B is so much faster!"      You should check it again
Profiling
Picking battles
DOM
DOM• DOM is slow• How slow?• http://jsperf.com/touching/4
DOM// DOMdiv.innerHTML += a;div.innerHTML += b;// stringvar html = ;html += a;html += b;div.innerHTML = html;
DOM
DOM + string concat• put things in perspective   http://jsperf.com/touching/5
ECMAland   DOMland
DOM•   caching DOM references•   caching length in collection loops•   "offline" changes in document fragment•   batch sty...
reflows   getComputedStyle(), or currentStyle in IE   bodystyle.color = red;   tmp = computed.backgroundColor;   bodystyle...
data attributes<div data-stuff="convenient"></div>• div.dataset.stuff• div.getAttribute(data-stuff)• Data.get(div).stuff /...
data attributes DIYvar Data = function() {  var warehouse = {};  var count = 1;  return {    set: function (dom, data) {  ...
data attributes
data attributes            http://jsperf.com/data-dataset
Shims and polyfills
Shims• pick the smaller/optimized one• one that uses native where available *• load conditionallye.g. JSON is non-native o...
Fast ECMAScript5 natives?• JDD: "browsers optimize loops because of  benchmarks"• http://jsperf.com/native-for-loop-vs-arr...
jQuery: the most popular polyfill• not free (perf-wise)• do you need it?
Cost of parsing and evaluating                  http://calendar.perfplanet.com/2011/laz                  y-evaluation-of-c...
Cost of parsing and evaluating
Experiment: jQuery vs. ZeptoWhat’s the cost of just dropping it on the page?
jsperf.com/zepto-jq-eval          […]
jsperf.com/zepto-jq-eval
jsperf.com/zepto-jq-eval
In closure…• JS off the critical path  (async, lazy, preload)• Practice writing jsperf.com tests  ("jsperf URL or it didnt...
Thank you!http://slideshare.net/stoyan/
JavaScript performance patterns
JavaScript performance patterns
JavaScript performance patterns
JavaScript performance patterns
JavaScript performance patterns
Nächste SlideShare
Wird geladen in …5
×

JavaScript performance patterns

11.508 Aufrufe

Veröffentlicht am

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

Veröffentlicht in: Technologie, Unterhaltung & Humor
2 Kommentare
33 Gefällt mir
Statistik
Notizen
Keine Downloads
Aufrufe
Aufrufe insgesamt
11.508
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
107
Aktionen
Geteilt
0
Downloads
141
Kommentare
2
Gefällt mir
33
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

JavaScript performance patterns

  1. 1. JavaScript Performance Patterns @stoyanstefanov frontendconf.ch Sept 6, 2012
  2. 2. JavaScript Performance Patterns
  3. 3. Importance of Performance http://bookofspeed.com
  4. 4. Importance of JavaScript Performance http://httparchive.org
  5. 5. // todo1. Loading JavaScript2. Runtime / UI / DOM + benchmarks + shims
  6. 6. Loading
  7. 7. First things first• reduce # of script files• gzip, shave 70% off• minify, extra 40-50%• Expires headers• CDN http://yslow.org PageSpeed http://webpagetest.org
  8. 8. <script src="http://…">
  9. 9. SPOF• Single point of failure• JS blocks http://phpied.com/3po-fail SPOF-O-Matic: https://chrome.google.com/webstore/detail/plikhggfbplemddobondkeogomgoodeg
  10. 10. Off the critical path
  11. 11. Asynchronous JS• <script defer>• <script async>• until then…
  12. 12. Dynamic script nodevar js = document.createElement(script);js.src = http://cdn.com/my.js;document.getElementsByTagName(head)[0].appendChild(js); http://calendar.perfplanet.com/2011/t he-art-and-craft-of-the-async-snippet/
  13. 13. But…, butt…, button?Q: <button onclick="…"?A: To hell with itQ: Dependencies?A: onload event and js.onreadystatechangeload(jquery.js, mystuff.js, function () { mystuff.go();});
  14. 14. Unblocking onload• Async JS blocks window.onload in !IE• May or may not be a problem• Theres a solution: FIF
  15. 15. <fif>frame-in-frame aka friendly frames aka this Meebo thing
  16. 16. FIF1) create iframe src="js:false"2) in the frame doc.write a <body onload …3) …that loads JS
  17. 17. 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();
  18. 18. FIF• unblocks onload, but…• more complex• requires JS changes
  19. 19. your script (before)// fun with window// and document
  20. 20. your script (before)(function() { // fun with window // and document}());
  21. 21. FIF (after)(function(window) { var document = window.document; // fun with window // and document}(parent.window));
  22. 22. FIF in the wild• experimental support in FB JS SDK• http://jsbin.com/axibow/1/edit
  23. 23. </fif>
  24. 24. Load JS but not execute• Use cases: – preload in anticipation – lazy
  25. 25. Preload, then eventually execute1. fetch the script, but don’t run it2. run it at some point (same as async JS)
  26. 26. Fetching• IE: dynamic script node, not in the DOM• All others: CORS (XHR2) – your CDN should let you specify Access-Control-Allow-Origin header or else!
  27. 27. 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);
  28. 28. // todo1. Loading JavaScript2. Runtime / UI / DOM + benchmarks + shims
  29. 29. Benchmarks• Lies, damn lies and performance advice• Test the wrong thing• Measure the wrong thing• Even if not, still draw the wrong conclusions
  30. 30. Your first benchmarkvar start = new Date();// loop 100000 timesvar took = new Date() – start;
  31. 31. Benchmark.js• by John-David Dalton• used in http://jsperf.com – calibrating the test – end time (ops/second) – statistical significance – margin of error
  32. 32. http://calendar.perfplanet.com/2010/bulletpro of-javascript-benchmarks/
  33. 33. Benchmarking browsers? No, thanks
  34. 34. Lets test!
  35. 35. String concatvar text = "";text += "moar";vs.var parts = [];parts.push(moar);var text = push.join(); http://jsperf.com/join-concat/
  36. 36. String concat
  37. 37. The pen is mightier than the sword! ** Only if the sword is very small and the pen very sharp
  38. 38. "Dont A, B is so much faster!" You should check it again
  39. 39. Profiling
  40. 40. Picking battles
  41. 41. DOM
  42. 42. DOM• DOM is slow• How slow?• http://jsperf.com/touching/4
  43. 43. DOM// DOMdiv.innerHTML += a;div.innerHTML += b;// stringvar html = ;html += a;html += b;div.innerHTML = html;
  44. 44. DOM
  45. 45. DOM + string concat• put things in perspective http://jsperf.com/touching/5
  46. 46. ECMAland DOMland
  47. 47. DOM• caching DOM references• caching length in collection loops• "offline" changes in document fragment• batch style changes• reducing reflows and repaints
  48. 48. reflows getComputedStyle(), or currentStyle in IE 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;
  49. 49. data attributes<div data-stuff="convenient"></div>• div.dataset.stuff• div.getAttribute(data-stuff)• Data.get(div).stuff // DIY
  50. 50. 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]; } };}();
  51. 51. data attributes
  52. 52. data attributes http://jsperf.com/data-dataset
  53. 53. Shims and polyfills
  54. 54. Shims• pick the smaller/optimized one• one that uses native where available *• load conditionallye.g. JSON is non-native only for 8% of users*, why load shim 100% of the time * http://html5please.us
  55. 55. 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
  56. 56. jQuery: the most popular polyfill• not free (perf-wise)• do you need it?
  57. 57. Cost of parsing and evaluating http://calendar.perfplanet.com/2011/laz y-evaluation-of-commonjs-modules/
  58. 58. Cost of parsing and evaluating
  59. 59. Experiment: jQuery vs. ZeptoWhat’s the cost of just dropping it on the page?
  60. 60. jsperf.com/zepto-jq-eval […]
  61. 61. jsperf.com/zepto-jq-eval
  62. 62. jsperf.com/zepto-jq-eval
  63. 63. In closure…• JS off the critical path (async, lazy, preload)• Practice writing jsperf.com tests ("jsperf URL or it didnt happen!")• Dont touch the DOM (remember the bridge)• Use the tools (Timeline, CPU/heap profiler, SpeedTracer, Dynatrace)• Think of poor mobile (easy with the shims)
  64. 64. Thank you!http://slideshare.net/stoyan/

×