Even Faster Web Sites
Steve Souders
souders@google.com
http://stevesouders.com/docs/sxsw-20090314.ppt
Disclaimer: This content does not necessarily reflect the opinions of my employer.
the importance of frontend performance
9% 91%
17%
83%
iGoogle, primed cache
iGoogle, empty cache
time spent on the frontend
www.aol.com www.ebay.com www.facebook.com www.google.com/search search.live.com/results www.msn.com www.myspace.com en.wikipedia.org/wiki www.yahoo.com www.youtube.com Empty Cache 97% 95% 95% 47% 67% 98% 98% 94% 97% 98% Primed Cache 97% 81% 81% 0% 0% 94% 98% 91% 96% 97%
April 2008
14 RULES
1. MAKE FEWER HTTP REQUESTS 2. USE A CDN 3. ADD AN EXPIRES HEADER 4. GZIP COMPONENTS 5. PUT STYLESHEETS AT THE TOP 6. PUT SCRIPTS AT THE BOTTOM 7. AVOID CSS EXPRESSIONS 8. MAKE JS AND CSS EXTERNAL 9. REDUCE DNS LOOKUPS 10.MINIFY JS 11.AVOID REDIRECTS 12.REMOVE DUPLICATE SCRIPTS 13.CONFIGURE ETAGS 14.MAKE AJAX CACHEABLE
25% discount code: "ssouders25"
Sept 2007
June 2009
Even Faster Websites
Split the initial payload Load scripts without blocking Couple asynchronous scripts Don't scatter inline scripts Split the dominant domain Flush the document early Use iframes sparingly Simplify CSS Selectors
Ajax performance (Doug Crockford) Writing efficient JavaScript (Nicholas Zakas) Creating responsive web apps (Ben Galbraith, Dion Almaer) Comet (Dylan Schiemann) Beyond Gzipping (Tony Gentilcore) Optimize Images (Stoyan Stefanov, Nicole Sullivan)
why focus on JavaScript?
Yahoo! Wikipedia eBay AOL MySpace YouTube Facebook
scripts block
only supported in IE (just landed in FF 3.1) script and main page domains can differ no need to refactor JavaScript
http://stevesouders.com/cuzillion/?ex=10013
document.write Script Tag
document.write("" + "");
parallelization only works in IE
parallel downloads for scripts, nothing else all document.writes must be in same script block
http://stevesouders.com/cuzillion/?ex=10014
load scripts without blocking
|| domains existing browser ensures downcan scripts busy order loads differ
size (bytes)
normal Script Src XHR Eval XHR Injection Script in Iframe Script DOM Element Script Defer document.write Script Tag
no IE,FF IE,FF IE,FF IE,FF IE IE*
yes no no no yes yes yes
yes no yes no yes yes yes
IE,FF no no IE,FF FF IE,FF IE,FF
IE,FF no no no FF IE IE
~50 ~500 ~500 ~50 ~200 ~50 ~100
*Only
other document.write scripts are downloaded in parallel (in the same script block).
asynchronous JS example: menu.js
script DOM element approach
before after
load scripts without blocking
|| domains existing browser ensures downcan scripts busy order loads differ
size (bytes)
normal Script Src XHR Eval XHR Injection Script in Iframe Script DOM Element Script Defer document.write Script Tag
no IE,FF IE,FF IE,FF IE,FF IE IE*
yes no no no yes yes yes
yes no yes no yes yes yes
IE,FF no no IE,FF FF IE,FF IE,FF
IE,FF no no no
~50 ~500 ~500 ~50
FF !IE ~200 IE ~50 IE ~100
*Only
other document.write scripts are downloaded in parallel (in the same script block).
what about
inlined code
that depends on the script?
coupling techniques
hardcoded callback window onload timer degrading script tags script onload
technique 5: script onload
pretty nice, medium complexity
case study: Google Analytics
recommended pattern:
1
document.write Script Tag approach blocks other resources
1http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55488
case study: dojox.analytics.Urchin
1
_loadGA: function(){ var gaHost = ("https:" == document.location.protocol) ? "https://ssl." : "http://www."; dojo.create('script', { src: gaHost + "google-analytics.com/ga.js" }, dojo.doc.getElementsByTagName("head")[0]); setTimeout(dojo.hitch(this, "_checkGA"), this.loadInterval); }, _checkGA: function(){ setTimeout(dojo.hitch(this, !window["_gat"] ? "_checkGA" : "_gotGA"), this.loadInterval); }, _gotGA: function(){ this.tracker = _gat._getTracker(this.acct); ... }
Script DOM Element approach "timer" coupling technique (script onload better)
1http://docs.dojocampus.org/dojox/analytics/Urchin
asynchronous loading & coupling
async technique: Script DOM Element
– easy, cross-browser – doesn't ensure script order
coupling technique: script onload
– fairly easy, cross-browser – ensures execution order for external script and inlined code
bad: stylesheet followed by inline script
browsers download stylesheets in parallel with other resources that follow...
...unless the stylesheet is followed by an inline script
http://stevesouders.com/cuzillion/?ex=10021
best to move inline scripts above stylesheets or below other resources use Link, not @import
don't scatter inline scripts
MSN Wikipedia eBay MySpace
iframes: most expensive DOM element
load 100 empty elements of each type
tested in all major 1 browsers
1IE
6, 7, 8; FF 2, 3.0, 3.1b2; Safari 3.2, 4; Opera 9.63, 10; Chrome 1.0, 2.0
iframes block onload
parent's onload doesn't fire until iframe and all its components are downloaded
workaround for Safari and Chrome: set iframe src in JavaScript
scripts block iframe
IE
script
Firefox
script
Safari Chrome Opera
script
no surprise – scripts in the parent block the iframe from loading
stylesheets block iframe (IE, FF)
IE
stylesheet
Firefox
stylesheet
Safari Chrome Opera
stylesheet
surprise – stylesheets in the parent block the iframe or its resources in IE & Firefox
stylesheets after iframe still block (FF)
IE
stylesheet
Firefox
stylesheet
Safari Chrome Opera
stylesheet
surprise – even moving the stylesheet after the iframe still causes the iframe's resources to be blocked in Firefox
iframes: no free connections
parent
iframe
iframe shares connection pool with parent (here – 2 connections per server in IE 7)
flush the document early
html image image script
html image image script
call PHP's flush()
gotchas:
– – – – –
PHP output_buffering – ob_flush() Transfer-Encoding: chunked gzip – Apache's DeflateBufferSize before 2.2.8 proxies and anti-virus software browsers – Safari (1K), Chrome (2K)
other languages:
$| or FileHandle autoflush (Perl), flush (Python), ios.flush (Ruby)
flushing and domain blocking
you might need to move flushed resources to a domain different from the HTML doc
html image image script html image image script
blocked by HTML document
different domains
case study: Google search
google image image script image 204
takeaways
focus on the frontend
run YSlow: http://developer.yahoo.com/yslow this year's focus: JavaScript speed matters
impact on revenue
Google: +500 ms -20% traffic1
Yahoo: +400 ms -5-9% full-page traffic Amazon: +100 ms -1% sales1
2
http://home.blarg.net/~glinden/StanfordDataMining.2006-11-29.ppt 2 http://www.slideshare.net/stoyan/yslow-20-presentation
1
cost savings
hardware – reduced load
bandwidth – reduced response size
http://billwscott.com/share/presentations/2008/stanford/HPWP-RealWorld.pdf
if you want better user experience more revenue reduced operating expenses the strategy is clear
Even Faster Web Sites
Steve Souders
souders@google.com
http://stevesouders.com/docs/sxsw-20090314.ppt