For much of its existence, JavaScript has been slow. No one complained until developers created complex web applications with thousands of lines of JavaScript code. Although newer JavaScript engines have improved the situation, there’s still a lot to understand about what makes JavaScript slow and what you can do to speed up your code.
41. 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
42. How Long Is Too Long? “0.1 second [100ms] is about the limit for having the user feel that the system is reacting instantaneously, meaning that no special feedback is necessary except to display the result.” - Jakob Nielsen
54. Result UI Thread Download See ya! Hello world! Parse Run time The UI thread needs to wait for the script to download, parse, and run before continuing
55. Result UI Thread Download See ya! Hello world! Parse Run Variable Constant Download time takes the longest and is variable
58. Result UI Thread JavaScript UI Update UI Update JavaScript JavaScript time The more scripts to download in between UI updates, the longer the page takes to render
62. Put Scripts at Bottom UI Thread JavaScript UI Update UI Update JavaScript JavaScript time Even if there are multiple scripts, the page renders quickly
74. Using Dynamic Scripts UI Thread See ya! Hello world! UI Update Run time Download Parse Only code execution happens on the UI thread, which means less blocking of UI updates
81. Deferred scripts begin to download immediately, but don't execute until all UI updates complete
82. Using <script defer> UI Thread See ya! Hello world! More UI Run More UI time Download Parse Similar to dynamic script nodes, but with a guarantee that execution will happen last
83. Timing Note:Although scripts always execute after UI updates complete, the order of multiple <script defer> scripts is not guaranteed across browsers
88. Using <script async> UI Thread See ya! Hello world! UI Update Run time Download Parse Download begins immediately and execution is slotted in at first available spot
93. //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
94. 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); }
95. When Clicked UI Thread time UI Queue UI Update onclick UI Update
96. When Clicked UI Thread UI Update time UI Queue onclick UI Update
97. When Clicked UI Thread onclick UI Update time UI Queue UI Update
98. When Clicked UI Thread UI Update UI Update onclick time UI Queue
99. After 25ms UI Thread UI Update UI Update onclick time UI Queue JavaScript
100. After 25ms UI Thread JavaScript UI Update UI Update onclick time UI Queue
101. After Another 25ms UI Thread JavaScript UI Update UI Update onclick time UI Queue JavaScript
102. After Another 25ms UI Thread JavaScript JavaScript UI Update UI Update onclick time UI Queue
105. //delay a function until after UI updates are done setImmediate(function(){ //code to execute here }); setImmediate() adds code to the UI queue after pending UI updates are finished
119. Web Workers Asynchronous JavaScript execution Execution happens outside the UI thread Doesn’t block UI updates Data-Driven API Data is serialized going into and out of the worker No access to DOM or BOM Separate execution environment
120. //in page var worker = new Worker("process.js"); worker.onmessage = function(event){ useData(event.data); }; worker.postMessage(values); //in process.js self.onmessage = function(event){ var items = event.data; for (var i=0,len=items.length; i < len; i++){ process(items[i]); } self.postMessage(items); };
121. When Clicked UI Thread time UI Queue UI Update onclick UI Update
122. When Clicked UI Thread UI Update time UI Queue onclick UI Update
123. When Clicked UI Thread onclick UI Update time UI Queue UI Update
124. When Clicked UI Thread onclick UI Update time UI Queue Worker Thread UI Update
125. When Clicked UI Thread UI Update UI Update onclick time UI Queue Worker Thread JavaScript
132. A repaint occurs when a visual change doesn't require recalculation of layout Changes to visibility, colors (text/background), background images, etc.
134. A reflowoccurs when a visual change requires a change in layout Initial page load ▪ browser resize ▪ DOM structure change ▪ layout style change layout information retrieved
136. Repaints and reflows are queued up as JavaScript executesand then executed in order
137. Reflow var 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!
140. Off-Document Operations Fast because there's no repaint/reflow Techniques: Remove element from the document, make changes, insert back into document Set element's display to “none”, make changes, set display back to default Build up DOM changes on a DocumentFragment then apply all at once
141. 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
142. DocumentFragment var 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
149. 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
159. Avoid Slow JavaScript Don't allow JavaScript to execute for more than 50ms Break up long JavaScript processes using: Timers Script Yielding (future) Web Workers
160.
161.
162. Etcetera My blog: www.nczonline.net Twitter: @slicknet These Slides: slideshare.net/nzakas Hire us: projects@stubbornella.org
Over the past couple of years, we've seen JavaScript development earn recognition as a true discipline. The idea that you should architect your code, use patterns and good programming practices has really elevated the role of the front end engineer. In my opinion, part of this elevation has been the adoption of what has traditionally been considered back end methodologies. We now focus on performance and algorithms, there's unit testing for JavaScript, and so much more. One of the areas that I've seen a much slower than adoption that I'd like is in the area of error handling.How many people have an error handling strategy for their backend? How many have dashboards that display problems with uptime and performance? How many have anything similar for the front end?Typically, the front end has been this black hole of information. You may get a few customer reports here and there, but you have no information about what's going on, how often it's occurring, or how many people have been affected.
So what have we talked about? Maintainable JavaScript is made up of four components.First is Code Conventions that describe the format of the code you’re writing.Second is Loose Coupling – keeping HTML, JavaScript, and CSS on separate layers and keeping application logic out of event handlers.Third is Programming Practices that ensure your code is readable and easily debugged.Fourth is creating a Build Process