JavaScript performance patterns

10,954 views
10,626 views

Published on

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

2 Comments
33 Likes
Statistics
Notes
No Downloads
Views
Total views
10,954
On SlideShare
0
From Embeds
0
Number of Embeds
102
Actions
Shares
0
Downloads
139
Comments
2
Likes
33
Embeds 0
No embeds

No notes for slide

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/

×