john lawrimore, 2014 javascript performance presenter john lawrimore...
TRANSCRIPT
Improving…
John Lawrimore, 2014
JavaScript Performance
Presenter
JOHN [email protected]@johnlawrimore
- Principal Consultant at Improving Enterprises- Microsoft enthusiast- Background heavy in web applications development- Unable to think of interesting things to say about self
Access this Presentation Online http://johnlawrimore.com/jsperformance
Objectives1. Provide a better understanding of how JavaScript works2. Introduce practices and techniques that will noticeably increase
performance3. Focus ONLY on what...
• Generally applies to all browsers• You can reasonably begin implementing tomorrow
Approaching Optimization• The right optimization strategy will differ by application• Do what makes sense• Pick your battles• Consider maintainability• Challenge your assumptions regularly
What is scope chain?
Scope Chain
Namespacing• Condenses the global namespace• Reduces search time for its descendants
HINT: Set distant namespaces to a variable to reduce search time
Closures (anonymous functions)Pros:• Access to variables outside the function
Cons:• Adds to the scope chain• Requires a new execution context
What’s wrong with this?
What’s wrong with this?
With and Try-Catch• Use Try-Catch sparingly• And NEVER try catch in a loop!
• NEVER use With
!
What’s missing?
Local variables missing the var keyword are automatically instantiated in the global namespace!!!
What’s missing?
Managing Scope• Don’t use the global namespace!• Cache out-of-scope variables referenced more than once• Limit augmentations to the scope chain• Closures• With• Try Catch
• Consider scope when creating prototypes• Don’t forget to use ‘var’
What is the DOM?
Document Object Model
Under the hood
What impacts DOM performance?
DOM Performance Issues
DOM search
DOM manipulation
!
!
What’s wrong with this?
THE DOM IS NOT A DATABASE!!
What’s wrong with this?
Data Property• Maintained within the JavaScript engine (not the DOM)• Can be global or bound to a specific element
Data vs. Attributes
Attribute Storage Data PropertyAvoids hits to the DOM
Accommodates types, arrays and complex objects
Optimized by built-in caching
Maintains valid HTML
Data vs. Attributes
What is Reflow/Repaint?
Repaint vs. ReflowREPAINTVisual changes that do not alter the document layout. (aka: redraw)
Examples:• Color• Font style
REFLOWOccurs when a visual change is made to the HTML document that requires layout to be computed.
Examples:• Initial render• Browser window resize• Visible elements added or removed• Element position changes• Changes in size, margin, border, etc.• Text changes• Layout information is retrieved (in some cases)
Repaint vs. Reflow
• Both are expensive in terms of performance because they require traversing• Reflow may or may not affect the entire document• JavaScript engines attempt to perform reflow in batches
Let’s improve this!
Let’s improve this!
Let’s improve this!
Let’s improve this!
DocumentFragment• Child of the document that created it• No visual representation• Construct happens behind the scenes• When passed to appended to document, only its children are added
CSS Transitions > Animation• Allows property changes in CSS values to occur smoothly over a
specified duration.• Powerful, clean, and faster than JS animations• Not supported in IE 9 and earlier
Avoiding Reflow• Group styles whenever possible
• Use classes or cssText instead of styles
• Accumulate new elements and append with one call• innerHTML (or html() for jQuery) • documentFragment
• Temporarily remove elements to be modified from the document• remove(), detach(), etc.
• Avoid animation, and leverage libraries or CSS transitions when you must
What is the outcome of this method?
What is the outcome of this method?
IT NEVER ENDS!!
HtmlCollectionsDon’t let them fool you! They are not arrays!
Examples:• document.getElementsByTagName• document.getElemenetsByClassName• document.images• document.forms
Let’s improve this!
Let’s improve this!
Only touch the HTMLCollection one time
Reducing DOM InteractionNever store data on the DOM
Avoid reflow
Limit calls to HtmlCollections
UI ThreadResponsibilities• Draw UI• Execute JavaScript
! UI THREAD CAN ONLY DO ONE RESPONSIBILITY AT A TIME
Timers• Run secondary tasks in the back ground AFTER the page has loaded.• When timer is done, job is added to the UI Queue.• Remember that less timers with more work is better than more timers
with less work.
Web Workers• New option for asynchronous execution in HTML5• Operates outside of UI Thread• Trigger specified event handlers when completed
What loop should I use?
Loopsfor
for-in
for-each
[].forEach()
$().each()
do-while
while
Selecting a LoopAvoid non-native function based loops• Creates closures (and associated overhead) in scope chain• Takes about 8-10x as long as basic for loop
Avoid for-in and for-each• for-in performs expensive type evaluation• for-each deprecated in ECMA -357
Selecting a LoopWhat matters?
• Amount of work being performed• Number of iterations
Do Less Work!!
Avoid lookups inside loop
Reduce number of calculation being performed
How can this be improved?
Combine control condition and control variable into a single statement
How can this be improved?
BET TER!
Combine the terminal condition evaluation w/ incrementing / decrementing
How can this be improved?
BET TER!
BEST!
Switch or If-Then-Else?
Selecting a Conditional StatementIt Depends!• As conditions increase, switch becomes more and more optimal
Let’s improve this!
Let’s improve this!
BET TER!Consider a combined approach!
Let’s improve this!
BET TER!
Create a hash table
OR EVEN
Common Pitfalls
What’s wrong here?
What’s wrong here?
What’s wrong here?
MEMORY LEAK!!
What’s wrong here?
MEMORY LEAK!!
Break the chain!
What’s wrong here?
What’s wrong here?
WILL BE CALLED WAY TOO MUCH!!
Throttle and Debounce• Throttling limits the execution of a function to no more than once
every delay milliseconds• Debouncing guarantees that the function will only ever be executed a
single time (given a specified threshold).
Smarter Coding
Which is better?
Which is better?
BET TER!
Use literals, avoid ‘new’
Which way is better?
Which way is better?
Use prototypes!
Reuse/Recycle
Reuse old variables instead of creating new ones!
Event DelegationHandle array element events with a single binding on the container• Events to bubble up the DOM tree• Detect the node originating the event and act accordingly• Use stopPropagation(), preventDefaults(), etc. as needed
Let’s improve this!
Let’s improve this!
BET TER!
Use lazy loading
String Manipulation Use += over function based concatenation
Use regexes to parse and slice
Which is faster?
Which is faster?
BET TER!
Use bitwise operators where appropriate
Traversing Always use the most optimum methods for crawling the DOM
• DOM properties such as childNode, firstChild, nextSibling, etc. don’t distinguish between element and other node types (such as spaces, comments, etc.)
JSONeval() SLOW!Libraries EVEN WORSE!
Always use the JSON namespace• Native in all modern browsers (IE8+)• JSON.parse()• JSON.stringify()• toJSON() prototype
!
Are libraries efficient?
Using LibrariesThe most optimal library is no match to the JavaScript Engine!• Intermediaries come with overhead• Native methods are compiled machine code
Leverage libraries only in cases where value is added…
Use native features over libraries• indexOf()
• lastIndexOf()
• every()
• filter()
• forEach()
• map()• some()
querySelectorAll()Much faster than using JavaScript and DOM to iterate and narrow down a list of elements• Supported in IE8+
What selector should I use?
SelectorsAll selectors are NOT created equal
Always consider what is going on underthe covers!
Type ExampleUniversal *
Type div
ID #header
Class .promo
Attribute [type=“text”]
Pseudo-class a:hover
Adjacent sibling h2 + p
Child li > ul
Descendant ul a
ID & Element Selectors$(‘#Element, form, input’)
Most optimal choice!
Backed by native DOM operations• eg. getElementById()
Class Selectors$(‘.element’)
Much slower selector• Particularly in browsers where getElementsByClassName() is not supported
!
Pseudo & Attribute$(‘:visible, :hidden’);$(‘[attribute=value]’);
USE SPARINGLY
No native calls available• querySelector() and querySelectorAll() help in modern browsers
!
Combining SelectorsSelector engines use the Right to Left Model
Always make your MOST SPECIFIC selector on the right
Let’s rank these!
A. $('.child', $('#parent')) B. $(‘#parent > .child’)
C. $parent.find(‘.child’) D. $(‘#parent .child’)
E. $(‘.child’, $parent) F. $parent.children(".child’)
Let’s rank these!
D. $(‘#parent .child’)
B. $(‘#parent > .child’)
F. $parent.children(".child’)
A. $('.child', $('#parent'))
E. $(‘.child’, $parent)
C. $parent.find(‘.child’)
RESULTS:
Can Script Tags Hurt Performance?
Script TagsPROBLEMS• External references result in an http request• Inline scripts circumvent client-side caching
Load Script Tags FasterALWAYS "minify" production code!
Bundle scripts (and styles) into single resources
Leverage Code Delivery Networks (CDN)
Lazy load scripts with AMD utilities
AMDAsynchronous Module Definition
Example: require.js
How do I Test Performance?
jsPerfCompare the performance of code snippets across browsers
YSlowGrade your site’s optimizations
Reading Material
High Performance JavaScriptNicholas C. Zakas