High Performance JavaScript (Amazon DevCon 2011)
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

High Performance JavaScript (Amazon DevCon 2011)

on

  • 8,260 views

 

Statistics

Views

Total Views
8,260
Views on SlideShare
8,205
Embed Views
55

Actions

Likes
22
Downloads
165
Comments
0

9 Embeds 55

http://know.namics.com 17
http://paper.li 10
http://minhyungko.blogspot.com 10
http://fe.com 10
http://www.linkedin.com 3
http://twitter.com 2
http://us-w1.rockmelt.com 1
http://www.slideshare.net 1
https://www.linkedin.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

High Performance JavaScript (Amazon DevCon 2011) Presentation Transcript

  • 1. High Performance JavaScript Nicholas C. Zakas | Amazon DevCon | April 27, 2011
  • 2. Whos this guy? Presentation Contributor, Architect Creator of YUI TestAuthor Lead Author Contributor Lead Author
  • 3. @slicknet(Complaints: @robertduffy)
  • 4. Does JavaScript performance matter?
  • 5. After all, all browsers now have optimizing JavaScript enginesTracemonkey/ V8 Squirrelfish Chakra KarakanJaegarMonkey (all) (4+) (9+) (10.5+) (3.5+)
  • 6. So our scripts are getting really, really fast
  • 7. Old computers ran slow applications Small amounts of CPU power and memory
  • 8. New computers are generally faster but slow applications still existMore CPU + more memory = less disciplined application development
  • 9. Right???
  • 10. Oh yeah, one more thing
  • 11. http://jeftek.com/1942/motorola-xoom-sunspider-results/
  • 12. Its still possible to write slowJavaScript on the new, faster JavaScript engines
  • 13. JavaScript performance directlyaffects user experience
  • 14. "Know the enemy and know yourself;in a hundred battles you will never be in peril." -Sun Tzu, The Art of War
  • 15. The UI ThreadThe brains of the operation
  • 16. The browser UI thread is responsible forboth UI updates and JavaScript execution Only one can happen at a time
  • 17. Jobs for UI updates and JavaScript execution are added to a UI queue Each job must wait in line for its turn to execute
  • 18. <button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button><script type="text/javascript">window.onload = function(){ document.getElementById("btn").onclick = function(){ //do something };};</script>
  • 19. Before ClickUI Threadtime UI Queue
  • 20. When ClickedUI Threadtime UI Queue UI Update onclick UI Update
  • 21. When ClickedUI Thread UI Updatetime UI Queue onclick Draw down state UI Update
  • 22. When ClickedUI Thread UI Update onclicktime UI Queue UI Update
  • 23. When ClickedUI Thread UI Update onclick UI Updatetime UI Queue Draw up state
  • 24. No UI updates while JavaScript is executing
  • 25. JavaScript May Cause UI Update<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button><script type="text/javascript">window.onload = function(){ document.getElementById("btn").onclick = function(){ var div = document.createElement(“div”); div.className = “tip”; div.innerHTML = “You clicked me!”; document.body.appendChild(div); };};</script>
  • 26. A UI update must use the latest info available
  • 27. Long-running JavaScript = Unresponsive UI
  • 28. Responsive UIUI Thread UI Update JavaScript UI Updatetime
  • 29. Unresponsive UIUI Thread UI Update JavaScript UI Updatetime
  • 30. The longer JavaScript runs,the worse the user experience
  • 31. The runaway script timer prevents JavaScript from running for too long Each browser imposes its own limit (except Opera)
  • 32. Internet Explorer
  • 33. Firefox
  • 34. Safari
  • 35. Chrome
  • 36. Runaway Script Timer Limits• Internet Explorer: 5 million statements• Firefox: 10 seconds• Safari: 5 seconds• Chrome: Unknown, hooks into normal crash control mechanism• Opera: none
  • 37. Does JIT compiling help?
  • 38. Interpreted JavaScriptUI Thread Interprettime
  • 39. JITed JavaScript (1st Run)UI ThreadCompile Executetime
  • 40. JITed JavaScript (After 1st Run)UI Thread Executetime
  • 41. How Long Is Too Long?“0.1 second [100ms] is about the limit forhaving the user feel that the system is reactinginstantaneously, meaning that no specialfeedback is necessary except to display theresult.” - Jakob Nielsen
  • 42. Translation: No single JavaScript job shouldexecute for more than 100ms to ensure a responsive UI
  • 43. Recommendation:Limit JavaScript execution to no more than 50ms measured on IE6 :)
  • 44. Doing so makes your application awesome
  • 45. Loadtime TechniquesDont let JavaScript interfere with page load performance
  • 46. During page load, JavaScripttakes more time on the UI thread
  • 47. <!doctype html><html><head> <title>Example</title></head><body> <p>Hello world!</p> <script src="foo.js"></script> <p>See ya!</p></body></html>
  • 48. ResultUI Thread UI Update JavaScript UI Updatetime
  • 49. ResultUI Thread Hello world! foo.js See ya!time
  • 50. ResultUI Thread Hello world! Download Parse Run See ya!time The UI thread needs to wait for the script to download, parse, and run before continuing
  • 51. ResultUI Thread Hello world! Download Parse Run See ya! Variable ConstantDownload time takes the longest and is variable
  • 52. Translation: The page doesnt render whileJavaScript is downloading, parsing, or executing during page load
  • 53. <!doctype html><html><head> <title>Example</title></head><body> <script src="foo.js"></script> <p>Hello world!</p> <script src="bar.js"></script> <p>See ya!</p> <script src="baz.js"></script> <p>Uh oh!</p></body></html>
  • 54. ResultUI Thread JavaScript UI Update JavaScript UI Update JavaScripttime The more scripts to download in between UI updates, the longer the page takes to render
  • 55. Technique #1: Put scripts at the bottom
  • 56. <!doctype html><html><head> <title>Example</title></head><body> <p>Hello world!</p> <p>See ya!</p> <script src="foo.js"></script></body></html>
  • 57. Put Scripts at BottomUI Thread UI Update UI Update JavaScript JavaScript JavaScripttime Even if there are multiple scripts, the page renders quickly
  • 58. Technique #2: Combine JavaScript files
  • 59. <!doctype html><html><head> <title>Example</title></head><body> <p>Hello world!</p> <p>See ya!</p> <script src="foo.js"></script> <script src="bar.js"></script> <script src="baz.js"></script></body></html>
  • 60. UI ThreadUI Update JavaScript JavaScript JavaScripttime Each script has overhead of downloading
  • 61. UI ThreadUI Update JavaScripttime Combining all of the files limits the networkoverhead and gets scripts onto the page faster
  • 62. <!doctype html><html><head> <title>Example</title></head><body> <p>Hello world!</p> <p>See ya!</p> <script src="foo-and-bar-and-baz.js"></script></body></html>
  • 63. Technique #3: Load scripts dynamically
  • 64. Basic Techniquevar script = document.createElement("script"), body;script.type = "text/javascript";script.src = "foo.js";body.insertBefore(script, body.firstChild);Dynamically loaded scripts are non-blocking
  • 65. Downloads no longer block the UI thread
  • 66. <!doctype html><html><head> <title>Example</title></head><body> <p>Hello world!</p> <script src="foo.js"></script> <p>See ya!</p></body></html>
  • 67. Using HTML <script>UI Thread Hello world! Download Parse Run See ya!time
  • 68. <!doctype html><html><head> <title>Example</title></head><body> <p>Hello world!</p> <script> var script = document.createElement("script"), body = document.body; script.type = "text/javascript"; script.src = "foo.js"; body.insertBefore(script, body.firstChild); </script> <p>See ya!</p><!-- more content --></body></html>
  • 69. Using Dynamic ScriptsUI Thread Hello world! See ya! Run UI Updatetime Download ParseOnly code execution happens on the UI thread, which means less blocking of UI updates
  • 70. function loadScript(url, callback){ var script = document.createElement("script"), body = document.body; script.type = "text/javascript"; if (script.readyState){ //IE <= 8 script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; callback(); } }; } else { //Others script.onload = function(){ callback(); }; } script.src = url; body.insertBefore(script, body.firstChild);}
  • 71. UsageloadScript("foo.js", function(){ alert("Loaded!");});
  • 72. Timing Note: Script execution begins immediatelyafter download and parse – timing of execution is not guaranteed
  • 73. Using Dynamic ScriptsUI Thread Hello world! Run See ya! UI Updatetime Download ParseDepending on time to download and script size, execution may happen before next UI update
  • 74. Technique #4: Defer scripts
  • 75. <!doctype html><html><head> <title>Example</title></head><body> <p>Hello world!</p> <script defer src="foo.js"></script> <p>See ya!</p> <!-- even more markup --></body></html>
  • 76. Support for <script defer>3.5 7.0 5.0 4.0 ?
  • 77. Deferred scripts begin to download immediately,but dont execute until all UI updates complete
  • 78. Using <script defer>UI Thread Hello world! See ya! More UI More UI Runtime Download Parse Similar to dynamic script nodes, but with a guarantee that execution will happen last
  • 79. Timing Note:Although scripts always execute after UI updates complete, the order ofmultiple <script defer> scripts is not guaranteed across browsers
  • 80. Technique #5: Asynchronous scripts
  • 81. <!doctype html><html><head> <title>Example</title></head><body> <p>Hello world!</p> <script async src="foo.js"></script> <p>See ya!</p> <!-- even more markup --></body></html>
  • 82. Support for <script async>3.6 7.0 5.0 ? ?
  • 83. Asynchronous scripts behave a lot like dynamic scripts
  • 84. Using <script async>UI Thread Hello world! See ya! Run UI Updatetime Download ParseDownload begins immediately and execution is slotted in at first available spot
  • 85. Note:Order of execution is explicitly notpreserved for asynchronous scripts
  • 86. Runtime TechniquesWays to ensure JavaScript doesnt run away
  • 87. function processArray(items, process, callback){ for (var i=0,len=items.length; i < len; i++){ process(items[i]); } callback();}
  • 88. Technique #1: Timers
  • 89. //create a new timer and delay by 500ms setTimeout(function(){ //code to execute here }, 500)setTimeout() schedules a function to be added to the UI queue after a delay
  • 90. function timedProcessArray(items, process, callback){ //create a clone of the original var todo = items.concat(); setTimeout(function(){ var start = +new Date(); do { process(todo.shift()); } while (todo.length > 0 && (+new Date() - start < 50)); if (todo.length > 0){ setTimeout(arguments.callee, 25); } else { callback(items); } }, 25);}
  • 91. When ClickedUI Threadtime UI Queue UI Update onclick UI Update
  • 92. When ClickedUI Thread UI Updatetime UI Queue onclick UI Update
  • 93. When ClickedUI Thread UI Update onclicktime UI Queue UI Update
  • 94. When ClickedUI Thread UI Update onclick UI Updatetime UI Queue
  • 95. After 25msUI Thread UI Update onclick UI Updatetime UI Queue JavaScript
  • 96. After 25msUI Thread UI Update onclick UI Update JavaScripttime UI Queue
  • 97. After Another 25msUI Thread UI Update onclick UI Update JavaScripttime UI Queue JavaScript
  • 98. After Another 25msUI Thread UI Update onclick UI Update JavaScript JavaScripttime UI Queue
  • 99. Technique #2: Web Workers
  • 100. Web Workers● Asynchronous JavaScript execution● Execution happens outside of UI thread ● Not on the UI thread = no UI delays● Data-driven API ● Data is serialized when sending data into or out of Worker ● No access to DOM, BOM ● Completely separate execution environment
  • 101. //in pagevar worker = new Worker("process.js");worker.onmessage = function(event){ useData(event.data);};worker.postMessage(values);//in process.jsself.onmessage = function(event){ var items = event.data; for (var i=0,len=items.length; i < len; i++){ process(items[i]); } self.postMessage(items);};
  • 102. When ClickedUI Threadtime UI Queue UI Update onclick UI Update
  • 103. When ClickedUI Thread UI Updatetime UI Queue onclick UI Update
  • 104. When ClickedUI Thread UI Update onclicktime UI Queue UI Update
  • 105. When ClickedUI Thread UI Update onclicktime Worker Thread UI Queue UI Update
  • 106. When ClickedUI Thread UI Update onclick UI Updatetime Worker Thread UI Queue JavaScript
  • 107. Worker Thread CompleteUI Thread UI Update onclick UI Updatetime UI Queue onmessage
  • 108. Worker Thread CompleteUI Thread UI Update onclick UI Update onmessagetime UI Queue
  • 109. Support for Web Workers3.5 4.0 4.0 ? 10.6
  • 110. Repaint and ReflowHidden performance costs of common operations
  • 111. Long UI updates =Unresponsive UI
  • 112. Unresponsive UIUI Thread UI Update JavaScript UI Updatetime
  • 113. JavaScript can causelong UI updates by triggering repaint and reflow
  • 114. A repaint occurs when a visual change doesnt require recalculation of layout Changes to visibility, colors (text/background), background images, etc.
  • 115. Repaint<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button><script type="text/javascript">window.onload = function(){ document.getElementById("btn").onclick = function(){ this.style.color = "#ff0"; };};</script> Repaint!
  • 116. A reflow occurs when a visual change requires a change in layoutInitial page load ▪ browser resize ▪ DOM structure change ▪ layout style change layout information retrieved
  • 117. Reflow<button id="btn" style="font-size: 30px; padding: 0.5em 1em">Click Me</button><script type="text/javascript">window.onload = function(){ document.getElementById("btn").onclick = function(){ var div = document.createElement(“div”); div.className = “tip”; div.innerHTML = “You clicked me!”; document.body.appendChild(div); };};</script> Reflow!
  • 118. Repaints and reflows are queued up as JavaScript executes and then executed in order
  • 119. Reflowvar list = document.getElementsByClassName("items")[0], i, item;for (i=0; i < 10; i++){ item = document.createElement("li"); item.innerHTML = "Item #" + i; list.appendChild(item);} Reflow x 10!
  • 120. Limiting repaints/reflowsimproves overall performance
  • 121. Technique #1Perform DOM manipulations off-document
  • 122. Off-Document Operations• Fast because theres no repaint/reflow• Techniques: – Remove element from the document, make changes, insert back into document – Set elements display to “none”, make changes, set display back to default – Build up DOM changes on a DocumentFragment then apply all at once
  • 123. DocumentFragment• A document-like object• Not visually represented• Considered to be owned by the document from which it was created• When passed to appendChild(), appends all of its children rather than itself
  • 124. DocumentFragmentvar list = document.getElementsByClassName("items")[0], fragment = document.createDocumentFragment(), i, item;for (i=0; i < 10; i++){ item = document.createElement("li"); item.innerHTML = "Item #" + i; fragment.appendChild(item);}list.appendChild(fragment); 1 Reflow
  • 125. Technique #2Group Style Changes
  • 126. Repaint! Reflow!element.style.color = "red";element.style.height = "100px"; Reflow!element.style.fontSize = "25px";element.style.backgroundColor = "white"; Repaint!
  • 127. Grouping Style Changes.active { color: red; height: 100px; fontSize: 25px; background-color: white;}element.className = "active"; Reflow!
  • 128. Grouping Style Changesvar item = document.getElementById("myItem");item.style.cssText = "color:red;height:100px;" + "font-size:25px;background-color: white"); Reflow!
  • 129. Technique #3Avoid Accidental Reflow
  • 130. Accidental Reflowelement.width = "100px";var width = element.offsetWidth; Reflow!
  • 131. What to do?• Minimize access to layout information – offsetTop, offsetLeft, offsetWidth, offsetHeight – scrollTop, scrollLeft, scrollWidth, scrollHeight – clientTop, clientLeft, clientWidth, clientHeight – Most computed styles• If a value is used more than once, store in local variable
  • 132. Does hardware acceleration help?
  • 133. Traditional RenderingUI Thread Compositing Drawingtime
  • 134. Hardware AccelerationUI Thread Prep Waittime Rendering info Signal complete Compositing Drawing GPU
  • 135. Recap
  • 136. The browser UI thread is responsible forboth UI updates and JavaScript execution Only one can happen at a time
  • 137. Responsive UIUI Thread UI Update JavaScript UI Updatetime
  • 138. Unresponsive UIUI Thread UI Update JavaScript UI Updatetime
  • 139. Unresponsive UIUI Thread UI Update JavaScript UI Updatetime
  • 140. Avoid Slow Loading JavaScript• Put scripts at the bottom• Concatenate scripts into as few files as possible• Choose the right way to load your scripts – Dynamically created scripts – Deferred scripts – Asynchronous scripts
  • 141. Avoid Slow JavaScript• Dont allow JavaScript to execute for more than 50ms• Break up long JavaScript processes using: – Timers – Web Workers
  • 142. Avoid Long UI Updates• Be careful of repaint and reflow• Perform complex DOM operations off- document – Remove elements and re-add them – Use DocumentFragment objects• Group style changes together• Avoid accidental reflow
  • 143. Dont be horrible
  • 144. Do be awesome
  • 145. The End
  • 146. Etcetera• My blog: www.nczonline.net• Twitter: @slicknet• These Slides: http://slideshare.net/nzakas/
  • 147. Creative Commons Images Used• http://www.flickr.com/photos/lrargerich/3115367361/• http://www.flickr.com/photos/hippie/2406411610/• http://www.flickr.com/photos/55733754@N00/3325000738/• http://www.flickr.com/photos/eurleif/255241547/• http://www.flickr.com/photos/off_the_wall/3444915939/• http://www.flickr.com/photos/wwarby/3296379139/• http://www.flickr.com/photos/derekgavey/4358797365/• http://www.flickr.com/photos/mulad/286641998/• http://www.flickr.com/photos/torley/2361164281/• http://www.flickr.com/photos/ottoman42/455242/• http://www.flickr.com/photos/goincase/3843348908/