Skip to main content
Speed Up Your JavaScript
          Nicholas C. Zakas
Principal Front End Engineer, Yahoo!
          x
   Web E ponents – June 4, 2009
Who's this guy?
• Principal Front End Engineer, Yahoo! Homepage
• YUI Contributor
• Author
Why slow?
Bad compilation?
No
No compilation!*

* Humor me for now. It'll make this easier.
Browsers
won't
help
your
code!!!!
Who will help
 your code?
JavaScript Performance Issues
•   Scope management
•   Data access
•   Loops
•   DOM
Scope Chains
When a Function Executes
• An execution context is created
• The context's scope chain is initialized with the
  members of the function's [[Scope]] collection
• An activation object is created containing all local
  variables
• The activation object is pushed to the front of the
  context's scope chain
Execution Context




Identifier Resolution
• Start at scope chain position 0
• If not found go to position 1
• Rinse, repeat
Identifier Resolution
• Local variables = fast!
• The further into the chain, the slower the
  resolution
Identifier Resolution (Reads)
                              200


                              180


                              160


                              140
                                                                                    Firefox 3
Time (ms) per 200,000 reads




                                                                                    Firefox 3.1 Beta 3
                              120                                                   Chrome 1
                                                                                    Chrome 2 Beta
                                                                                    Internet Explorer 7
                              100
                                                                                    Internet Explorer 8
                                                                                    Opera 9.64
                              80                                                    Opera 10 Alpha
                                                                                    Safari 3.2
                                                                                    Safari 4 Beta
                              60


                              40


                              20


                               0
                                    1       2    3                      4   5   6
                                                     Identifier Depth
Identifier Resolution (Writes)
                               200


                               180


                               160


                               140
                                                                                      Firefox 3
Time (ms) per 200,000 writes




                                                                                      Firefox 3.1 Beta 3
                               120                                                    Chrome 1
                                                                                      Chrome 2 Beta
                                                                                      Internet Explorer 7
                               100
                                                                                      Internet Explorer 8
                                                                                      Opera 9.64
                               80                                                     Opera 10 Alpha
                                                                                      Safari 3.2
                                                                                      Safari 4 Beta
                               60


                               40


                               20


                                0
                                     1       2     3                      4   5   6
                                                       Identifier Depth
Scope Chain Augmentation
• The with statement
• The catch clause of try-catch
• Both add an object to the front of the scope chain
Inside of Global Function
Inside of with/catch Statement




• Local variables now in second slot
• with variables now in first slot
“with statement
considered harmful”
-Douglas Crockford
Closures
• The [[Scope]] property of closures begins with two
  objects
• Calling the closure means three objects in the
  scope chain (minimum)
Closures
Inside of Closure
Recommendations
• Store out-of-scope variables in local variables
   – Especially global variables
• Avoid the with statement
   – Adds another object to the scope chain, so local
     function variables are now one step away
   – Use local variables instead
• Be careful with try-catch
   – The catch clause also augments the scope chain
• Use closures sparingly
• Don't forget var when declaring variables
JavaScript Performance Issues
•   Scope management
•   Data access
•   Loops
•   DOM
Places to Access Data
•   Literal value
•   Variable
•   Object property
•   Array item
Data Access Performance
• Accessing data from a literal or a local variable is
  fastest
   – The difference between literal and local variable is
     negligible in most cases
• Accessing data from an object property or array
  item is more expensive
   – Which is more expensive depends on the browser
Data Access
                              100



                              90



                              80



                              70
Time (ms) per 200,000 reads




                              60
                                                                                                                                                              Literal
                                                                                                                                                              Local Variable
                              50
                                                                                                                                                              Array Item
                                                                                                                                                              Object Property
                              40



                              30



                              20



                              10



                               0
                                    Firefox 3   Firefox 3.1   Chrome 1   Chrome 2    Internet     Internet    Opera 9.64   Opera 10   Safari 3.2   Safari 4
                                                  Beta 3                   Beta     Explorer 7   Explorer 8                 Alpha                   Beta
Property Depth
• object.name < object.name.name
• The deeper the property, the longer it takes to
  retrieve
Property Depth
                              250




                              200




                                                                      Firefox 3
Time (ms) per 200,000 reads




                                                                      Firefox 3.1 Beta 3
                              150                                     Chrome 1
                                                                      Chrome 2 Beta
                                                                      Internet Explorer 7
                                                                      Internet Explorer 8
                                                                      Opera 9.64
                              100                                     Opera 10 Alpha
                                                                      Safari 3.2
                                                                      Safari 4 Beta




                              50




                               0
                                    1    2                    3   4
                                             Property Depth
Property Notation
• Difference between object.name and
  object[“name”]?
  – Generally no
  – Exception: Dot notation is faster in Safari
Recommendations
• Store these in a local variable:
   – Any object property accessed more than once
   – Any array item accessed more than once
• Minimize deep object property/array item lookup
-5%   -10%   -33%
JavaScript Performance Issues
•   Scope management
•   Data Access
•   Loops
•   DOM
Loops
• ECMA-262, 3rd Edition:
  –   for
  –   for-in
  –   do-while
  –   while
• ECMA-357, 2nd Edition:
  – for each
Which loop?
It doesn't matter!
What Does Matter?
• Amount of work done per iteration
   – Includes terminal condition evaluation and
     incrementing/decrementing
• Number of iterations
• These don't vary by loop type
Fixing Loops
• Decrease amount of work per iteration
• Decrease number of iterations
Easy Fixes
• Eliminate object property/array item lookups
Easy Fixes
• Eliminate object property/array item lookups
• Combine control condition and control variable
  change
   – Work avoidance!
Two evaluations:
j < len
j < len == true
One evaluation
j-- == true




                 -50%
Easy Fixes
• Eliminate object property/array item lookups
• Combine control condition and control variable
  change
   – Work avoidance!
Things to Avoid for Speed
• ECMA-262, 3rd Edition:
   – for-in
               nd
• ECMA-357, 2 Edition:
   – for each
• ECMA-262, 5th Edition:
   – array.forEach()
• Function-based iteration:
   –   jQuery.each()
   –   Y.each()
   –   $each
   –   Enumerable.each()
• Introduces additional function
• Function requires execution (execution context
  created, destroyed)
• Function also creates additional object in scope
  chain

                                              8x
JavaScript Performance Issues
•   Scope management
•   Data Access
•   Loops
•   DOM
DOM
HTMLCollection
HTMLCollection Objects
• document.images, document.forms,
  etc.
• getElementsByTagName()
• getElementsByClassName()
Note: Collections in the HTML DOM are assumed to be live
meaning that they are automatically updated when the underlying
                      document is changed.
Infinite Loop!
HTMLCollection Objects
• Look like arrays, but aren't
   – Bracket notation
   – length property
• Represent the results of a specific query
• The query is re-run each time the object is
  accessed
   – Include accessing length and specific items
   – Much slower than accessing the same on arrays
   – Exceptions: Opera, Safari
15x   53x   68x
=   =   =
HTMLCollection Objects
• Minimize property access
   – Store length, items in local variables if used frequently
• If you need to access items in order frequently,
  copy into a regular array
function array(items){
    try {
        return Array.prototype.slice.call(items);
    } catch (ex){
        var i      = 0,
            len    = items.length,
            result = Array(len);

        while (i < len){
            result[i] = items[i];
            i++;
        }
    }

    return result;
}
Reflow
Reflow is the process by
which the geometry of the
layout engine's formatting
objects are computed.
           - Chris Waterson, Mozilla
When Reflow?
•   Initial page load
•   Browser window resize
•   DOM nodes added or removed
•   Layout styles applied
•   Layout information retrieved
Reflow!
DocumentFragment
• A document-like object
• Not visually represented
• Considered a child of the document from which it
  was created
• When passed to addChild(), appends all of
  its children rather than itself
No
      reflow!


Reflow!
When Reflow?
•   Initial page load
•   Browser window resize
•   DOM nodes added or removed
•   Layout styles applied
•   Layout information retrieved
Reflow!             Reflow!




          Reflow!
What to do?
• Minimize changes on style property
• Define CSS class with all changes and just
  change className property
Reflow!
When Reflow?
•   Initial page load
•   Browser window resize
•   DOM nodes added or removed
•   Layout styles applied
•   Layout information retrieved
    – Only if reflow is cached
Reflow?
              Reflow?




    Reflow?
What to do?
• Minimize access to layout information
• If a value is used more than once, store in local
  variable
Speed Up Your DOM
•   Be careful using HTMLCollection objects
•   Perform DOM manipulations off the document
•   Change CSS classes, not CSS styles
•   Be careful when accessing layout information
Will it be like this forever?
No
Browsers With Optimizing Engines
•   Chrome (V8)
•   Safari 4+ (Nitro)
•   Firefox 3.5+ (TraceMonkey)
•   Opera 10? 11? (Carakan)

All use native code generation and JIT compiling to
        achieve faster JavaScript execution.
Hang in there!
Summary
•   Mind your scope
•   Local variables are your friends
•   Function execution comes at a cost
•   Keep loops small
•   Avoid doing work whenever possible
•   Minimize DOM interaction
•   Use a good browser and encourage others to do
    the same
Questions?
Etcetera
• My blog:    www.nczonline.net
• My email:   nzakas@yahoo-inc.com
• Twitter:    @slicknet
Creative Commons Images Used
•   http://www.flickr.com/photos/blackbutterfly/3051019058/
•   http://www.flickr.com/photos/23816315@N07/2528296337/
•   http://www.flickr.com/photos/37287477@N00/515178157/
•   http://www.flickr.com/photos/ottoman42/455242/
•   http://www.flickr.com/photos/crumbs/2702429363/
•   http://flickr.com/photos/oberazzi/318947873/