You are on page 1of 63

Even Faster Web Sites
Disclaimer: This content does not necessarily reflect the opinions of my employer.

the importance of frontend performance
9% 91%



iGoogle, primed cache

iGoogle, empty cache

time spent on the frontend Empty Cache 97% 95% 95% 47% 67% 98% 98% Primed Cache 97% 81% 81% 0% 0% 94% 98%

94% 97% 98%

91% 96% 97%
April 2008

greater potential for improvement simpler proven to work . Start there.The Performance Golden Rule 80-90% of the end-user response time is spent on the frontend.




Sept 2007 .

June 2009 .


....... Nicole Sullivan ...Dylan Schiemann Going beyond gzipping..Even Faster Web Sites Splitting the initial payload Loading scripts without blocking Coupling asynchronous scripts Positioning inline scripts Sharding dominant domains Flushing the document early Using iframes sparingly Simplifying CSS Selectors Understanding Ajax performance..Doug Crockford Creating responsive web apps.......................Nicholas Zakas Scaling with Comet...... Dion Almaer Writing efficient JavaScript...............................Tony Gentilcore Optimizing images.Stoyan Stefanov...............Ben Galbraith...

Why focus on JavaScript? Yahoo! Wikipedia eBay AOL MySpace YouTube Facebook .

Chr What's Cuzillion? . Saf 3 7 secs: IE 8. FF 3.scripts block <script src="A.5(?). Chr 2. Saf 4 http://stevesouders.js"> blocks parallel downloads and rendering 9 secs: IE 6-7. Op 9-10. FF 3. www.Splitting the Initial Payload JavaScript Functions Executed before onload 115K 183K 1088K 15K 17K 131K 297K 114K 321K 240K 252K avg 30% 44% 9% 45% 24% 31% 18% 32% 13% 18% 26% avg .

tools needed to automate this (Doloto from Microsoft) load scripts without blocking – how? .Splitting the Initial Payload split your JavaScript between what's needed to render the page and everything else load "everything else" after the page is rendered separate manually (Firebug).

createElement("script").type="text/javascript".src=e.onload=k.appendChild(c) . p. c.getElementsByTagName("HEAD")[0]. var c=g.onerror=c. c. c. parallel scripts MSN Scripts and other resources downloaded in parallel! How? Secret sauce?! var p= g.onreadystatechange=n.

write Script Tag .Loading Scripts Without Blocking XHR Eval XHR Injection Script in Iframe Script DOM Element Script Defer document.

com/A.appendChild(se).Script DOM Element var se = document. document.createElement('script').src = 'http://anydomain.getElementsByTagName('head') [0].com/cuzillion/?ex=10010 . script and main page domains can differ no need to refactor JavaScript http://stevesouders. se.js'.

browser busy indicators .

FF no no IE.FF IE ~100 *Only other document.FF IE no yes yes no yes yes IE.FF FF IE.write scripts are downloaded in parallel (in the same script block).write Script Tag IE.FF no no ~50 ~500 ~500 Script in Iframe Script DOM Element Script Defer document.FF IE.FF yes no no yes no yes IE.FF no FF IE ~50 ~200 ~50 IE* yes yes IE.FF IE.Loading Scripts Without Blocking || domains existing browser ensures downcan scripts busy order loads differ size (bytes) normal Script Src XHR Eval XHR Injection no IE. .

. XHR Eval XHR Injection Script in iframe Script DOM Element Script Defer different domains same domains Script DOM Element Script Defer no order preserve order no order preserve order XHR Eval XHR Injection Script in iframe Script DOM Element (IE) Script DOM Element (FF) Script Defer (IE) Managed XHR Eval Managed XHR Injection no busy show busy Script DOM Element Script DOM Element (FF) Script Defer (IE) Managed XHR Injection Managed XHR Eval no busy show busy Script DOM Element (FF) Script Defer (IE) Managed XHR Eval Managed XHR Injection XHR Injection XHR Eval Script DOM Element (IE) Managed XHR Injection Managed XHR Eval Script DOM Element ..and the winner is.


src = "menu. ['couple-xhr-eval.createMenu('examplesbtn'. function init() { EFWS.php'.createElement('script'). . aExamples). var aExamples = [ ['couple-normal. </script> . 'Normal Script Src'].js script DOM element approach <script type="text/javascript"> var domscript = document.appendChild(domscri pt). document. 'XHR Eval']. domscript.asynchronous JS example: menu.getElementsByTagName('head')[0].. 'Managed XHR'] ].php'. ['managed-xhr.js".Menu.php'. } init()..

before after .

FF no no IE.FF IE.FF yes no no yes no yes IE.FF FF IE.write scripts are downloaded in parallel (in the same script block).Loading Scripts Without Blocking || domains existing browser ensures downcan scripts busy order loads differ size (bytes) normal Script Src XHR Eval XHR Injection no IE.FF no no ~50 ~500 ~500 Script in Iframe Script DOM Element Script Defer document. .write Script Tag IE.FF no ~50 FF !IE ~200 IE ~50 IE* yes yes IE.FF IE no yes yes no yes yes IE.FF IE ~100 *Only other document.FF IE.

what about inlined code that depends on the script? .

coupling techniques hardcoded callback window onload timer degrading script tags script onload .

createMenu('examplesbtn'.Menu.onloadDone = false. medium complexity .php'.getElementsByTagName('head')[0].createElement('script')... domscript. domscript. function init() { EFWS. } domscript.readyState ) { if ( ! domscript.onloadDone = true. domscript. } } document.appendChild(domscript).onloadDone = true.js".]. } domscript. .src = "menu. }.onloadDone ) { init(). } var domscript = document. domscript.onreadystatechange = function() { if ( "loaded" === domscript. </script> pretty nice. aExamples).onload = function() { if ( ! domscript. 'Normal Script Src'].onloadDone ) { init().technique 5: script onload <script type="text/javascript"> var aExamples = [['couple-normal.

cross-browser ensures execution order for external script and inlined code multiple interdependent external and inline scripts: much more complex (see hidden slides) concatenate your external scripts into one! . cross-browser doesn't ensure script order coupling technique: script onload fairly easy.asynchronous loading & coupling async technique: Script DOM Element easy.

com/cuzillion/?ex=10021 best to move inline scripts above stylesheets or below other resources use Link...unless the stylesheet is followed by an inline script http://stevesouders.. not @import ..bad: stylesheet followed by inline script browsers download stylesheets in parallel with other resources that follow. .

Positioning Inline Scripts MSN Wikipedia eBay MySpace .

Sharding Dominant Domains but Rule 9 says "Reduce DNS lookups"?! remove DNS lookups that aren't heavily used split domains that are on the critical path how find "critical path"? .

com .yahoo.www. .google.

5.4 Chrome Opera 9 2 6 2 6 4 6 4 HTTP/1.1 IE 6.0 4 6 8 6 4 6 4 newer browsers open more connections* best to shard across 2-4 domains** * .com/blog/2008/03/20/roundup-on-parallel-connections/ ** http://yuiblog.connections per server by browser HTTP/1.stevesouders.7 IE 8 Firefox 1. 2 Firefox 3 Safari 3.

flush (Python).2. ios.flushing the document early html image image script html image image script gotchas: call PHP's flush() PHP output_buffering – ob_flush() Transfer-Encoding: chunked gzip – Apache's DeflateBufferSize before 2.flush (Ruby) other languages: . Chrome (2K) HTML document blocks resources $| or FileHandle autoflush (Perl).8 proxies and anti-virus software browsers – Safari (1K).

successful flushing Google Search google image image script image 204 external resource downloaded early content visible to the user .com/images/nav_logo4.

0).Using Iframes Sparingly most expensive DOM element blocks parent's onload workaround: set iframe src via setTimeout <iframe id=if1 src=""></iframe> <script type="text/javascript"> function setSrc() { document. } setTimeout(setSrc. </script> .src="url".getElementById('if1').

types of CSS selectors ID selectors: #toc {} class selectors: .chapter {} type selectors: A {} adjacent sibling selectors: H1 + #toc {} child selectors: #toc > LI {} descendant selectors: #toc A {} universal selectors: * {} attribute selectors: href="#index"] {} psuedo classes and elements: A:hover {} .

org/en/Writing_Efficient_CSS "The style system matches a rule by starting with the rightmost selector and moving to the left through the rule's selectors. } find every LI whose parent is id="toc" #toc A { color: #444. As long as your little subtree continues to check out.mozilla.writing efficient CSS https://developer. the style system will continue moving to the left until it either matches the rule or bails out because of a mismatch. } find every A and climb its ancestors until id="toc" or DOM root (!) is found ." #toc > LI { font-weight: bold.

com MySpace 2289 305 2882 92 376 1038 932 1628 588 1966 552 449 886 444 Avg Depth 13 14 17 8 12 11 9 Wikipedia Yahoo! YouTube average 795 800 821 1033 1333 564 817 923 10 13 9 12 .real world levels of CSS # Rules # elements AOL eBay Facebook Google Search Live Search MSN.

class0007 { ..testing typical CSS 1K rules (vs.stevesouders. } http://www. 20K) same amount of CSS in all test pages 30 ms avg delta "costly"selectors aren't always costly (at typical levels) are these selectors "costly"? DIV DIV DIV P .

..testing expensive selectors 1K rules (vs. } DIV DIV DIV P A. } the key is the key selector – the rightmost argument ..class0007 * { .class0007 { . 20K) same amount of CSS in all test pages 2126 ms avg delta! truly expensive selector compare to: A..

Simplifying CSS Selectors efficient CSS comes at a cost – page weight focus optimization on selectors where the key selector matches many elements reduce the number of selectors .

com/ .org/ (in progress) Hammerhead CSS Sprite Generator http://spritegen.Performance Tools HttpWatch SpriteMe Cuzillion Firebug YSlow Page Speed http://code.

Performance Analyzers: HPWS rules combine JS & CSS use CSS sprites use a CDN set Expires in the future gzip text responses put CSS at the top put JS at the bottom avoid CSS expressions make JS & CSS external reduce DNS lookups minify JS avoid redirects remove dupe scripts remove ETags YSlow Page Speed Pagetest X X X X X X X X X X X X X X X X X X X X X X X X X VRTA neXpert X X X X X X X X X X .

uncompressed size optimize images shard domains flush the document avoid iframes simplify CSS selectors X X X VRTA neXpert X X X X X X .Performance Analyzers: EFWS rules YSlow Page Speed Pagetest don't block UI thread split JS payload load scripts async inline JS b4 stylesheet write efficient JS min.

Performance Analyzers: other rules
YSlow Page Speed Pagetest use persistent conns reduce cookies avoid net congestion increase MTU, TCP win avoid server congestion remove unused CSS specify image dims use GET for Ajax reduce DOM elements avoid 404 errors avoid Alpha filters don't scale images optimize favicon 2.0 X X X VRTA neXpert X X X X X X X X 2.0 2.0 2.0 2.0 2.0 2.0


Top 10 Performance
YSlow Page Speed
AOL ?* yellow

eBay Facebook Google Search Live Search MySpace Wikipedia Yahoo! YouTube
* YSlow wouldn't start.

82 68 95 93 72 84 66 96 77

yellow red green green yellow yellow yellow yellow yellow

combine 6 scripts, 8 stylesheets

add Expires header
minify JavaScript, save 39K (36%)

avoid inline script after stylesheet
31K (41%) unused CSS remove ETags 46K (49%) unused CSS ~90 very inefficient CSS selectors .Yahoo! shard l.

long HTML doc response 2. remove ETags (?) 11. sharded domains – pics & rtm (good) 8.2 3 1 4 4 4 4 5 www.ebay. thumbs load slowly – HTTP/1. 4. ads .playgrnd * {} 6 7 8 9 .com 1. flush (good) 3.js var pageName='HomePagePortal'.js non-blocking (good) 6.0? 10. ~40 inefficient CSS selectors . inline script blocks . 26 bg images – no sprites 7. scripts block 5. compress images by 20% 9. combine 8 scripts simplify CSS selectors avoid inline script after stylesheet jQueryEnabled = true. remove 97K (49%) unused CSS .AOL shard portal.

Facebook combine 13 scripts. 6 stylesheets sprite 31 background images reduce images by 106K (44%) put stylesheets above scripts remove 102K (50%) unused CSS . combine 13 scripts sprite 26 background images put stylesheets above scripts avoid inline script after stylesheet .

save ~29K (14% .YouTube add Expires header (can't?) minify JavaScript.

7 secs xfer size: 436K YSlow: F (48) opportunities load oreo.js async split i.combined.0 downgrade requests: 107 load time: across two domains concatenate 10 scripts sprite 25 CSS background images 30 resources with short Expires 62% (62K) of CSS not used Performance Analysis cool flushed document HTTP/1.moo.

shopping. 20%) • remove ETags .com • slow spots: • top – shard CSS and JS.http://www. flush • middle – shard images • bottom – scripts (async?) • use CSS sprites (42 bg images) • add future Expires header • optimize images (50K.

takeaways focus on the frontend run Page Speed and YSlow 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.2006-11-29.slideshare.ppt 2 1 .net/~glinden/StanfordDataMining.

cost savings hardware – reduced load bandwidth – reduced response size http://billwscott.pdf .com/share/presentations/2008/stanford/HPWP-RealWorld.

if you want better user experience more revenue reduced operating expenses the strategy is clear Even Faster Web Sites .

ppt .com Souders souders@google.