High-Performance JavaScript: Why Everything You¶ve Been Taught is Wrong

Joseph Smarr Plaxo, Inc.

About me
Chief Platform Architect at Plaxo
First employee (March 2002) Architect and lead developer for Plaxo Online

-

Abusing web browsers since 1993 (Mosaic)
Plaxo Online 2.0 (AJAX via iframes in 2004) JavaScript Wormhole (OSCON 06)

http://JosephSmarr.com
Joseph Smarr, Plaxo, Inc.

About Plaxo
Smart Address Book
Syncs address book and calendar with lots of places User updates their contact info you get it automatically

-

Founded in 2002, ~50 employees, 15M+ users
Backed by Sequoia, Ram Shriram, Tim Koogle, et al

http://www.plaxo.com
Joseph Smarr, Plaxo, Inc.

Plaxo Online
AJAX Desktop beta.plaxo.com ‡ Flexible desktop ‡ Contacts ‡ Calendar ‡ Tasks ‡ Notes ‡ Sync dashboard ‡ Pulse ‡ Profile / settings

Joseph Smarr, Plaxo, Inc.

Plaxo Online
AJAX Desktop beta.plaxo.com ‡ Flexible desktop ‡ Contacts ‡ Calendar ‡ Tasks ‡ Notes ‡ Sync dashboard ‡ Pulse ‡ Profile / settings

Joseph Smarr, Plaxo, Inc.

Plaxo Online
AJAX Desktop beta.plaxo.com ‡ Flexible desktop ‡ Contacts ‡ Calendar ‡ Tasks ‡ Notes ‡ Sync dashboard ‡ Pulse ‡ Profile / settings

Joseph Smarr, Plaxo, Inc.

Looks great«but it almost didn¶t ship!
Spring 06: ³Let¶s really push the envelope for Plaxo 3.0´ Summer 06: ³Wow, these are great UI ideas, keep em coming´ Fall 06: ³Let¶s put 7 great web devs full time on this´¶ Winter 06: ³Ok, we built a ton«now let¶s optimize it, no problem´ March 07: ³Uh oh, making it fast is way harder than we thought´ April 07: ³We can¶t ship this as is²do we need to start over?!?´ June 07: ³After a heroic effort, it¶s just barely fast enough (phew!)´

Joseph Smarr, Plaxo, Inc.

Where did we go wrong??
Didn¶t take performance seriously from day one Didn¶t think the browser¶s limitations were significant Didn¶t use the app daily as we were developing it Didn¶t push back on feature requests for performance Didn¶t value perceived performance / responsiveness

-

«overcoming these challenges required unlearning a lot of standard assumptions about building software«

Joseph Smarr, Plaxo, Inc.

Why Everything You¶ve Been Taught is Wrong
AJAX euphoria
Web browsers can be made to do anything now! Use desktop / OOP programming style

-

Why it¶s wrong
Browsers are being pushed beyond their comfort zone JavaScript code is parsed & interpreted every time line of source code cost per

Joseph Smarr, Plaxo, Inc.

Why High-Performance JavaScript Matters
Everyone is amazed by fast apps
It hardly matters what else they do!

-

Everyone hates slow apps
It hardly matters what else they do«

-

AJAX was supposed to be all about responsiveness!!

- Having tried and almost failed, we now have a mantra:
Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra
- Be Lazy - Be Responsive - Be Pragmatic - Be Vigilant

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra
- Be Lazy: Nothing is faster than doing nothing - Be Responsive - Be Pragmatic - Be Vigilant

Joseph Smarr, Plaxo, Inc.

Write less code
-

Be Lazy: Nothing is faster than doing nothing

Initial parsing of JavaScript is often a major bottleneck
No JIT, no cached object code, interpreted every time Parse time is non-linear in the size of total JavaScript?

-

Can¶t rely on browser caching to excuse large code size
Yahoo study: surprising number of hits with empty cache Frequent code releases frequently need to re-download

-

More code = more to download, execute, maintain, etc.
Ideal for large AJAX apps is <500K JS uncompressed

Joseph Smarr, Plaxo, Inc.

Total code size of some AJAX apps
d) (KB, u i 1,000 S 500 0 Zi b Y M il ! Pl x (b ) k Pl x ( ) b Milk M b G il G C l l d Pl x ( u ) d 2,500 2,000

1,500

Joseph Smarr, Plaxo, Inc.

Write less code
-

Be Lazy: Nothing is faster than doing nothing

Minimize the JavaScript code you send down
Minify = good, obfuscate = not much better Strip debug / logging lines (don¶t just set log-level = 0) Remove unnecessary OOP boilerplate Get/Set functions don¶t actually protect member vars! etc.

-

Minimize dependency on third-party library code
Lots of extra code comes along that you don¶t need Libraries solve more general problems use like scaffolding

Joseph Smarr, Plaxo, Inc.

Load JavaScript on-demand
-

Be Lazy: Nothing is faster than doing nothing

Once you¶ve written less code, load it only as-needed ³I work hard at
Break into classes / modules; use require / provide (ala dojo)

being lazy´

-

Bundle classes into packages to minimize server round-trips
Packages should ignore pre-loaded dependencies Tradeoff of downloading shared code twice vs. multiple round trips (e.g. for common widgets)

-

Build packages with error-handler hook for development
Will re-build from source every time if you don¶t write
Ryan ³Roger´ Moore

Joseph Smarr, Plaxo, Inc.

Draw UI as late as possible
Never pre-draw hidden UI if you can avoid it

Be Lazy: Nothing is faster than doing nothing

Draw less DOM = faster to draw, browser less saturated

Cache previously drawn HTML when appropriate
But have to know when to invalidate the cache

Don¶t keep hidden UI up-to-date behind the scenes
Just re-draw next time you show it (simpler, one-time cost)

Consider re-drawing vs. partial dynamic UI updates
Redraw is often faster / easier / less code

Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI
Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI
Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI
Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI
Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI
Joseph Smarr, Plaxo, Inc.

How to Be Lazy
¥ Write less code! ¥ Load JS on-demand ¥ Draw UI as late as possible

Be Lazy: Nothing is faster than doing nothing

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra
- Be Lazy - Be Responsive: Jump when the user says jump - Be Pragmatic - Be Vigilant

Joseph Smarr, Plaxo, Inc.

Minimize initial perceived load time
Put CSS at the top of your page and JS at the bottom Draw major placeholder UI with ³loading«´ first Load / draw your app in stages (lazy, on-demand)

Be Responsive: Jump when the user says jump

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Joseph Smarr, Plaxo, Inc.

Yield early and often
-

Be Responsive: Jump when the user says jump

Always want to show a quick response acknowledgement
But browser often doesn¶t update UI until your code returns!

-

Solution: do minimum work, use setTimeout(0) to yield
Use closures to chain state together with periodic pauses Draw UI progressively, with loading messages as needed Use onmousedown instead of onclick (~100msec faster!) Demo: http://josephsmarr.com/oscon-js/yield.html

Joseph Smarr, Plaxo, Inc.

Cache backend responses and ³Data structures
Requesting code always assumes async response

Be Responsive: Jump when the user says jump

All data requests should go through data-manager code
Request as needed and cache results for subsequent asks

AJAX²together at last!´

-

Use range caches
-

only fill in missing pieces

Ideal for partial views into long lists of data
Glenn ³Fiddich´ Dixon

Balance local updates vs. re-fetching from APIs
-

Do the easy cases, but beware of too much update code Worst case = trash cache and re-fetch = first-time case

Joseph Smarr, Plaxo, Inc.

How to Be Responsive

Be Responsive: Jump when the user says jump

¥ Minimize initial perceived loading time ¥ Yield early and often for responsive UI ¥ Cache API responses with data-manager layer

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra
- Be Lazy - Be Responsive - Be Pragmatic: Don¶t make things even harder - Be Vigilant

Joseph Smarr, Plaxo, Inc.

Play to the browser¶s strengths
Avoid dynamic CSS-class definitions & CSS math

Be Pragmatic: Don¶t make things even harder

Avoid DOM manipulation; use innerHTML and array.join(³´)

Avoid reflow when possible (esp. manually on browser resize) Avoid memory allocation (e.g. string-splitting) Do DOM manipulation off-DOM, then re-insert at the end

Joseph Smarr, Plaxo, Inc.

Cheat when you can / should
Use global functions or IDs when reasonable
-

Be Pragmatic: Don¶t make things even harder

Finding by class / attaching event handlers is slow Protect modularity only when needed (e.g. widgets)

-

Directly attach onclick, etc. handlers instead of using event listeners where appropriate Use fastest find-elems available when you need to scan the DOM (don¶t rely on general-purpose code)

Joseph Smarr, Plaxo, Inc.

Inline initial API calls & HTML
-

Be Pragmatic: Don¶t make things even harder

Tempting to load blank page and do everything in JavaScript
Have to redraw UI dynamically; don¶t want two copies of UI code

-

Problem: initial load is usually too slow
Too many round-trips to the server; too long before initial UI shows up

-

Solution: if you have to do it every time, do it statically
Save out initial API responses in web page Use data-manager to hide pre-fetching (can change your mind later) Download initial HTML in web page

Joseph Smarr, Plaxo, Inc.

How to Be Pragmatic
¥ Play to the browser¶s strengths ¥ Cheat when you can / should

Be Pragmatic: Don¶t make things even harder

¥ Inline initial API calls / HTML for faster load time

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra
- Be Lazy - Be Responsive - Be Pragmatic - Be Vigilant: Only you can prevent slow web apps

Joseph Smarr, Plaxo, Inc.

Profile like crazy
-

Be Vigilant: Only you can prevent slow web apps

Bottlenecks abound and are usually not obvious
Use firebug¶s profiler (Joe Hewitt, you rule! ) Use timestamp diffs and alerts Comment-out blocks of code

-

Measure with a consistent environment
Browsers bog down always restart first

Try multiple runs and average (and don¶t forget the cache)

Joseph Smarr, Plaxo, Inc.

Firebug is your friend

Joseph Smarr, Plaxo, Inc.

Consider performance from day one
Apps get slow when you make them do many / slow things! Consider how much code / work is needed for each feature
Is it making the browser work against the grain? What else is suffering for this feature? Is it worth it?

Be Vigilant: Only you can prevent slow web apps

-

Make sure everyone remembers how important speed is

Joseph Smarr, Plaxo, Inc.

Get your priorities straight
-

Be Vigilant: Only you can prevent slow web apps

Building high-performance apps requires the right attitude
Must consider and prioritize speed in every decision

-

Ask ³what features can I add within this size / speed?´ vs. ³how small / fast can I get this set of features?´
I had to learn this the hard way (Plaxo 3.0 almost didn¶t ship!)
³Performance first, features second!´
Todd & Cam

Joseph Smarr, Plaxo, Inc.

How to Be Vigilant
¥ Profile like crazy

Be Vigilant: Only you can prevent slow web apps

¥ Consider performance from day one ¥ Get your priorities straight

Joseph Smarr, Plaxo, Inc.

Conclusion:

Avoid making the same mistakes we did
Make the browser happy « and it will make you happy Web browsers are more like mobile phones than desktops
Limited, flimsy, temperamental platform being stretched beyond its initial design goals But everyone¶s got one, so it¶s still the best place to be

-

Don¶t push the limits unless you have to
Often, small quick-loading pages with AJAX interactions is best Sometimes you really do need rich, interactive controls

Joseph Smarr, Plaxo, Inc.

Just Remember:
-

Everything You¶ve Been Taught is Wrong
Think about performance ² early and often Write as little code as you need ² each line has a cost Do what the browser wants (whenever possible) Remember the high-performance JavaScript mantra:
Be lazy Be responsive Be pragmatic Be vigilant

http://JosephSmarr.com

Joseph Smarr, Plaxo, Inc.

Sign up to vote on this title
UsefulNot useful