48
High-Performance JavaScript: Why Everything You’ve Been Taught is Wrong Joseph Smarr Plaxo, Inc.

Smarr Oscon 2007

Embed Size (px)

Citation preview

Page 1: Smarr Oscon 2007

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

Joseph Smarr

Plaxo, Inc.

Page 2: Smarr Oscon 2007

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

Page 3: Smarr Oscon 2007

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

Page 4: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Plaxo OnlineAJAX Desktopbeta.plaxo.com

• Flexible desktop • Contacts• Calendar• Tasks• Notes• Sync dashboard• Pulse• Profile / settings

Page 5: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Plaxo OnlineAJAX Desktopbeta.plaxo.com

• Flexible desktop • Contacts• Calendar• Tasks• Notes• Sync dashboard• Pulse• Profile / settings

Page 6: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Plaxo OnlineAJAX Desktopbeta.plaxo.com

• Flexible desktop • Contacts• Calendar• Tasks• Notes• Sync dashboard• Pulse• Profile / settings

Page 7: Smarr Oscon 2007

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!)”

Page 8: Smarr Oscon 2007

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…

Page 9: Smarr Oscon 2007

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 cost per line of source code

Page 10: Smarr Oscon 2007

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:

Page 11: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra

- Be Lazy

- Be Responsive

- Be Pragmatic

- Be Vigilant

Page 12: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra

- Be Lazy: Nothing is faster than doing nothing

- Be Responsive

- Be Pragmatic

- Be Vigilant

Page 13: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Write less code - 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

Be Lazy: Nothing is faster than doing nothing

Page 14: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

0

500

1,000

1,500

2,000

2,500

Zimbra Yahoo!Mail

Plaxo(before)

Renkoo Plaxo(after)

Rememberthe Milk

Meebo Gmail GoogleCalendar

Plaxo(startup)

JS

co

de

siz

e (

KB

, un

co

mp

res

se

d)

Total code size of some AJAX apps

Page 15: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Write less code- 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

Be Lazy: Nothing is faster than doing nothing

Page 16: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Load JavaScript on-demand- Once you’ve written less code, load it only as-needed

- Break into classes / modules; use require / provide (ala dojo)

- 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

Be Lazy: Nothing is faster than doing nothing

“I work hard at being lazy”

Ryan “Roger” Moore

Page 17: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Draw UI as late as possible- Draw less DOM = faster to draw, browser less saturated

- Never pre-draw hidden UI if you can avoid it

- 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

Be Lazy: Nothing is faster than doing nothing

Page 18: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI

Page 19: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI

Page 20: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI

Page 21: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI

Page 22: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Never pre-draw hidden UI

Page 23: Smarr Oscon 2007

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

Page 24: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra

- Be Lazy

- Be Responsive: Jump when the user says jump

- Be Pragmatic

- Be Vigilant

Page 25: Smarr Oscon 2007

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

Page 26: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Page 27: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Page 28: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Page 29: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Page 30: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Page 31: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Page 32: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Load your app in stages

Page 33: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Yield early and often- 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

Be Responsive: Jump when the user says jump

Page 34: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Cache backend responses- All data requests should go through data-manager code

- Request as needed and cache results for subsequent asks

- Requesting code always assumes async response

- Use range caches only fill in missing pieces

- Ideal for partial views into long lists of data

- 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

Be Responsive: Jump when the user says jump

“Data structures and AJAX—together at last!”

Glenn “Fiddich” Dixon

Page 35: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

How to Be Responsive √ Minimize initial perceived loading time

√ Yield early and often for responsive UI

√ Cache API responses with data-manager layer

Be Responsive: Jump when the user says jump

Page 36: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra

- Be Lazy

- Be Responsive

- Be Pragmatic: Don’t make things even harder

- Be Vigilant

Page 37: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Play to the browser’s strengths- Avoid DOM manipulation; use innerHTML and array.join(“”)

- Avoid dynamic CSS-class definitions & CSS math

- 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

Be Pragmatic: Don’t make things even harder

Page 38: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

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

- 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)

Be Pragmatic: Don’t make things even harder

Page 39: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Inline initial API calls & HTML- 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

Be Pragmatic: Don’t make things even harder

Page 40: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

How to Be Pragmatic √ Play to the browser’s strengths

√ Cheat when you can / should

√ Inline initial API calls / HTML for faster load time

Be Pragmatic: Don’t make things even harder

Page 41: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

The High-Performance JS Mantra

- Be Lazy

- Be Responsive

- Be Pragmatic

- Be Vigilant: Only you can prevent slow web apps

Page 42: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Profile like crazy- 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)

Be Vigilant: Only you can prevent slow web apps

Page 43: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

Firebug is your friend

Page 44: Smarr Oscon 2007

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?

- Make sure everyone remembers how important speed is

Be Vigilant: Only you can prevent slow web apps

Page 45: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

- 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!)

Get your priorities straightBe Vigilant: Only you can prevent slow web apps

“Performance first, features second!”

Todd & Cam

Page 46: Smarr Oscon 2007

Joseph Smarr, Plaxo, Inc.

How to Be Vigilant √ Profile like crazy

√ Consider performance from day one

√ Get your priorities straight

Be Vigilant: Only you can prevent slow web apps

Page 47: Smarr Oscon 2007

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

Page 48: Smarr Oscon 2007

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 vigilanthttp://JosephSmarr.com