Steve Souders Even Faster Web Sites Disclaimer: This content does not necessarily.

Slides:



Advertisements
Similar presentations
High Performance Web Sites 14 rules for faster pages
Advertisements

Web 2.0 Programming 1 © Tongji University, Computer Science and Technology. Web Web Programming Technology 2012.
Optimizing Websites with YSlow Tom Lianza Co-Founder Wishlisting.com Tom Lianza Co-Founder Wishlisting.com.
Building Fast 3rd-Party Webapps O'Reilly Velocity Web Performance and Operations Conference 24 June Lessons.
Steve Souders Even Faster Websites Disclaimer: This content does not necessarily reflect.
Steve Souders Even Faster Themes Disclaimer: This content does not necessarily reflect.
17% 83% iGoogle, primed cache the importance of frontend performance 9%91% iGoogle, empty cache.
High Performance Web Sites Essential Knowledge for Frontend Engineers
17% 83% iGoogle, primed cache the importance of frontend performance 9%91% iGoogle, empty cache.
Episodes a shared approach for timing web pages Steve Souders Google Disclaimer: This content does not necessarily reflect.
Steve Souders Even Faster Web Sites Disclaimer: This content does not necessarily.
Steve Souders Even Faster Web Sites best practices for faster pages Disclaimer: This.
Steve Souders Even Faster Web Sites Disclaimer: This content does not necessarily reflect.
Steve Souders Even Faster Web Sites (inside ma.tt) best practices for faster pages.
17% 83% iGoogle, primed cache the importance of frontend performance 9%91% iGoogle, empty cache.
CS193H: High Performance Web Sites Lecture 4: Class Projects Steve Souders Google
Steve Souders Even Faster Web Sites Disclaimer: This content does not necessarily.
CS193H: High Performance Web Sites Lecture 22: Vol 2 – Optimize Images, Use Iframes Sparingly, Flush the Document Early Steve Souders Google
Steve Souders High Performance Widgets Disclaimer: This content does not necessarily.
Steve Souders Life's too short, write fast code part 1 Disclaimer: This content does.
Steve Souders Even Faster Web Sites best practices for faster pages Disclaimer:
CS193H: High Performance Web Sites Lecture 1: Introduction Steve Souders Google
17% 83% iGoogle, primed cache the importance of frontend performance 9%91% iGoogle, empty cache.
CS193H: High Performance Web Sites Lecture 17: Rule 14 – Make Ajax Cacheable Steve Souders Google
Steve Souders Even Faster Web Sites Disclaimer: This content does not necessarily reflect.
CS193H: High Performance Web Sites Lecture 21: Vol 2 – Split Dominant Domains Steve Souders Google
High Performance Web Sites Essential Knowledge for Frontend Engineers
Exceptional Performance Evolution at Yahoo! Steve Souders Chief Performance Yahoo!
Steve Souders Even Faster Web Sites Disclaimer: This content does not necessarily reflect.
CS193H: High Performance Web Sites Lecture 6: Use a CDN Steve Souders Google
Steve Souders Even Faster Web Sites Disclaimer: This content does not necessarily reflect.
Steve Souders Even Faster Web Sites Disclaimer: This content does not necessarily.
Steve Souders Even Faster Web Sites best practices for faster pages Disclaimer: This content does not necessarily.
Steve Souders Life's too short, write fast code part 1 Disclaimer: This content does.
CS193H: High Performance Web Sites Lecture 20: Vol 2 – Don't Scatter Inline Scripts Steve Souders Google
Steve Souders Even Faster Web Sites best practices for faster pages Disclaimer: This content does not necessarily.
CS193H: High Performance Web Sites Lecture 5: Make Fewer HTTP Requests Steve Souders Google
CS193H: High Performance Web Sites Lecture 12: Rule 8 – Make JavaScript and CSS External Steve Souders Google
CS193H: High Performance Web Sites Lecture 19: Vol 2 – Load Scripts Without Blocking Steve Souders Google
CS193H: High Performance Web Sites Lecture 10: Rule 6 – Put Scripts at the Bottom Steve Souders Google
CS193H: High Performance Web Sites Lecture 2: The Importance of Frontend Performance Steve Souders Google
CS193H: High Performance Web Sites Lecture 11: Rule 7 – Avoid CSS Expressions Rule 9 – Reduce DNS Lookups Steve Souders Google
CS193H: High Performance Web Sites Lecture 18: Vol 2 – Split the Initial Payload Steve Souders Google
Web Performance Meetup 1 Web Performance 101 Jeremy
Web Performance Meetup 1 Web Performance Toolbelt Jeremy
Stevesouders.com/docs/velocity-wpo pptx Disclaimer: This content does not necessarily reflect the opinions of my employer.
Web Site Performance What makes web sites slow? Back end Front end Tools for measuring performance Firebug / YSlow Visual Studio Test Edition W3.org html.
CS193H: High Performance Web Sites Lecture 24: Vol 2 – CSS Descendant Selectors, Forced Compression Steve Souders Google
HIGH LEVEL OVERVIEW: CSS CSS SYNTAX CONSISTS OF A SET OF RULES THAT HAVE 3 PARTS: A SELECTOR, A PROPERTY, AND A VALUE. IT’S NOT NECESSARY TO REMEMBER THIS.
PHP Meetup - SEO 2/12/2009. Where to Focus? Ensuring the findability of content Ensuring content is well understood by search engines Maximizing the importance.
The DOM tree CS The DOM tree CS380 2 Types of DOM nodes  element nodes (HTML tag)  can have children and/or attributes  text nodes (text in.
Cascading Style Sheets
In this lecture, you will learn: ❑ How to link between pages of your site ❑ How to link to other sites ❑ How to structure the folders on your web site.
“Cascading Style Sheets” for styling WWW information DSC340 Mike Pangburn.
Disclaimer: This content does not necessarily reflect the opinions of my employer.
High Performance Websites (Based on Steve Souder’s lecture) By Bhoomi Patel.
Disclaimer: This content does not necessarily reflect the opinions of my employer.
&.zip Disclaimer: This content does not necessarily reflect the opinions of my employer.
Mark Phillip markphillip.com 200s, 304s, Expires Headers, HTTP Compression, And You.
Disclaimer: This content does not necessarily reflect the opinions of my employer.
Performance, SEO, Accessibility Ivan Zhekov Telerik Corporation
Web Performance Optimization Boban Stojanovski (Senior Front End Developer at Solaborate) Think Fast by default.
PERFORMANCE ENHANCEMENT IN ASP.NET By Hassan Tariq Session #1.
Web Technologies Lecture 7 Synchronous vs. asynchronous.
Enhance Your Page Load Speed And Improve Traffic.
Even Faster Web Sites best practices for faster pages
Even Faster Web Sites best practices for faster pages
Even Faster Web Sites cc:
CSE 154 Lecture 22: AJAX.
High Performance Mobile
Presentation transcript:

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

17% 83% iGoogle, primed cache the importance of frontend performance 9%91% iGoogle, empty cache

time spent on the frontend Empty CachePrimed Cache search.live.com/results67%0% en.wikipedia.org/wiki94%91% April 2008

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

Sept 2007

June 2009

14 R ULES 1.M AKE FEWER HTTP REQUESTS 2.U SE A CDN 3.A DD AN E XPIRES HEADER 4.G ZIP COMPONENTS 5.P UT STYLESHEETS AT THE TOP 6.P UT SCRIPTS AT THE BOTTOM 7.A VOID CSS EXPRESSIONS 8.M AKE JS AND CSS EXTERNAL 9.R EDUCE DNS LOOKUPS 10.M INIFY JS 11.A VOID REDIRECTS 12.R EMOVE DUPLICATE SCRIPTS 13.C ONFIGURE ET AGS 14.M AKE AJAX CACHEABLE

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 Ben Galbraith, Dion Almaer Writing efficient JavaScript Nicholas Zakas Scaling with Comet Dylan Schiemann Going beyond gzipping Tony Gentilcore Optimizing images Stoyan Stefanov, Nicole Sullivan

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

scripts block blocks parallel downloads and rendering 7 secs: IE 8, FF 3.5(?), Chr 2, Saf 4 What's Cuzillion? 9 secs: IE 6-7, FF 3.0, Chr 1, Op 9-10, Saf 3

a tool for quickly constructing web pages to see how components interact Open Source Cuzillion 'cuz there are a zillion pages to check

JavaScript Functions Executed before onload % search.live.com/results17K24% en.wikipedia.org/wiki114K32% % avg 252K avg 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); tools needed to automate this (Doloto from Microsoft) load scripts without blocking – how?

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

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

XHR Eval script must have same domain as main page must refactor script var xhrObj = getXHRObject(); xhrObj.onreadystatechange = function() { if ( xhrObj.readyState != 4 ) return; eval(xhrObj.responseText); }; xhrObj.open('GET', 'A.js', true); xhrObj.send('');

XHR Injection var xhrObj = getXHRObject(); xhrObj.onreadystatechange = function() { if ( xhrObj.readyState != 4 ) return; var se=document.createElement('script'); document.getElementsByTagName('head') [0].appendChild(se); se.text = xhrObj.responseText; }; xhrObj.open('GET', 'A.js', true); xhrObj.send(''); script must have same domain as main page

Script in Iframe <iframe src='A.html' width=0 height=0 frameborder=0 id=frame1> iframe must have same domain as main page must refactor script: // access iframe from main page window.frames[0].createNewDiv(); // access main page from iframe parent.document.createElement('div');

Script DOM Element var se = document.createElement('script'); se.src = ' document.getElementsByTagName('head') [0].appendChild(se); script and main page domains can differ no need to refactor JavaScript

Script Defer only supported in IE (just landed in FF 3.1) script and main page domains can differ no need to refactor JavaScript

document.write Script Tag document.write(" "); parallelization only works in IE parallel downloads for scripts, nothing else all document.write s must be in same script block

browser busy indicators

status bar progress bar logocursor block render block onload normal Script Src FFIE,FF FFIE,FF XHR Eval no XHR Injection no Script in Iframe IE,FFFFIE,FFFFnoIE,FF Script DOM Element FF noFF Script Defer FF IE,FF document.write Script Tag FFIE,FF FFIE,FF good to show busy indicators when the user needs feedback bad when downloading in the background

Ensure scripts execute in order: necessary when scripts have dependencies IE: FF: Avoid scripts executing in order: faster – first script back is executed immediately ensure/avoid ordered execution

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

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

Loading Scripts Without Blocking don't let scripts block other downloads you can still control execution order, busy indicators, and onload event What about inline scripts?

synchronous JS example: menu.js var aExamples = [ ['couple-normal.php', 'Normal Script Src'], ['couple-xhr-eval.php', 'XHR Eval'],... ['managed-xhr.php', 'Managed XHR'] ]; function init() { EFWS.Menu.createMenu('examplesbtn', aExamples); } init();

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

before after

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

what about inlined code that depends on the script?

baseline coupling results (not good) Preserve Execution Order Load Script & Image in Parallel normal Script Src allIE8, Saf4, Chr2 XHR Eval -all XHR Injection -all Script in Iframe -all Script DOM Element FF, OpIE, FF, Saf, Chr Script Defer FF, Saf, Chr, OpIE, (Saf4, Chr2) * document.write Script Tag allSaf4, Chr2 * Scripts download in parallel regardless of the Defer attribute. need a way to load scripts asynchronously AND preserve order

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

technique 1: hardcoded callback var aExamples = [['couple-normal.php', 'Normal Script Src'],...]; function init() { EFWS.Menu.createMenu('examplesbtn', aExamples); } var domscript = document.createElement('script'); domscript.src = "menu.js"; document.getElementsByTagName('head')[0].appendChild(domscri pt); init() is called from within menu.js not very flexible doesn't work for 3 rd party scripts

technique 2: window onload var aExamples = [['couple-normal.php', 'Normal Script Src'],...]; function init() { EFWS.Menu.createMenu('examplesbtn', aExamples); } if ( window.addEventListener ) { window.addEventListener("load", init, false); } else if ( window.attachEvent ) { window.attachEvent("onload", init); } init() is called at window onload must use async technique that blocks onload: Script in Iframe does this across most browsers init() called later than necessary

technique 3: timer var domscript = document.createElement('script'); domscript.src = "menu.js"; document.getElementsByTagName('head')[0].appendChild(domscript); var aExamples = [['couple-normal.php', 'Normal Script Src'],...]; function init() { EFWS.Menu.createMenu('examplesbtn', aExamples); } function initTimer(interval) { if ( "undefined" === typeof(EFWS) ) { setTimeout(initTimer, interval); } else { init(); } initTimer(300); load if interval too low, delay if too high slight increased maintenance – EFWS

John Resig's degrading script tags var aExamples = [['couple-normal.php', 'Normal Script Src'],...]; function init() { EFWS.Menu.createMenu('examplesbtn', aExamples); } init(); at the end of menu-degrading.js: var scripts = document.getElementsByTagName("script"); var cntr = scripts.length; while ( cntr ) { var curScript = scripts[cntr-1]; if (curScript.src.indexOf("menu-degrading.js") != -1) { eval( curScript.innerHTML ); break; } cntr--; } cleaner clearer safer – inlined code not called if script fails no browser supports it

technique 4: degrading script tags var aExamples = [['couple-normal.php', 'Normal Script Src'],...]; function init() { EFWS.Menu.createMenu('examplesbtn', aExamples); } var domscript = document.createElement('script'); domscript.src = "menu-degrading.js"; if ( -1 != navigator.userAgent.indexOf("Opera") ) { domscript.innerHTML = "init();"; } else { domscript.text = "init();"; } document.getElementsByTagName('head')[0].appendChild(domscript); elegant, flexible (cool!) not well known doesn't work for 3 rd party scripts (unless...)

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

what about multiple scripts that depend on each other, and inlined code that depends on the scripts? two solutions: Managed XHR DOM Element and Doc Write

multiple script example: menutier.js var aRaceConditions = [['couple-normal.php', 'Normal...]; var aWorkarounds = [['hardcoded-callback.php', 'Hardcod...]; var aMultipleScripts = [['managed-xhr.php', 'Managed XH...]; var aLoadScripts = [['loadscript.php', 'loadScript'],...]; var aSubmenus = [["Race Conditions", aRaceConditions], ["Workarounds", aWorkarounds], ["Multiple Scripts", aMultipleScripts], ["General Solution", aLoadScripts]]; function init() { EFWS.Menu.createTieredMenu('examplesbtn', aSubmenus); }

technique 1: managed XHR var aRaceConditions = [['couple-normal.php', 'Normal...]; var aWorkarounds = [['hardcoded-callback.php', 'Hardcod...]; var aMultipleScripts = [['managed-xhr.php', 'Managed XH...]; var aLoadScripts = [['loadscript.php', 'loadScript'],...]; var aSubmenus = [["Race Conditions", aRaceConditions],...]; function init() { EFWS.Menu.createTieredMenu('examplesbtn', aSubmenus); } EFWS.Script.loadScriptXhrInjection("menu.js", null, true); EFWS.Script.loadScriptXhrInjection("menutier.js", init, true); XHR Injection asynchronous technique does not preserve order – we have to add that before after

EFWS.loadScriptXhrInjection // Load an external script. // Optionally call a callback and preserve order. loadScriptXhrInjection: function(url, onload, bOrder) { var iQ = EFWS.Script.queuedScripts.length; if ( bOrder ) { var qScript = { response: null, onload: onload, done: false }; EFWS.Script.queuedScripts[iQ] = qScript; } var xhrObj = EFWS.Script.getXHRObject(); xhrObj.onreadystatechange = function() { if ( xhrObj.readyState == 4 ) { if ( bOrder ) { EFWS.Script.queuedScripts[iQ].response = xhrObj.responseText; EFWS.Script.injectScripts(); } else { eval(xhrObj.responseText); if ( onload ) { onload(); } }; xhrObj.open('GET', url, true); xhrObj.send(''); } process queue (next slide)or... eval now, call callback save response to queue add to queue (if bOrder)

EFWS.injectScripts // Process queued scripts to see if any are ready to inject. injectScripts: function() { var len = EFWS.Script.queuedScripts.length; for ( var i = 0; i < len; i++ ) { var qScript = EFWS.Script.queuedScripts[i]; if ( ! qScript.done ) { if ( ! qScript.response ) { // STOP! need to wait for this response break; } else { eval(qScript.response); if ( qScript.onload ) { qScript.onload(); } qScript.done = true; } ready for this script, eval and call callback bail – need to wait to preserve order if not yet injected preserves external script ordernon-blocking works in all browserscouples with inlined code works with scripts across domains

technique 2: DOM Element and Doc Write Preserve Execution Order Load Scripts in Parallel Load Script & Image in Parallel Script DOM Element FF, Op FF, Op, IE, Saf, Chr FF, IE, Saf, Chr Script Defer IE, Saf, Chr, FF, Op IE document.write Script Tag IE, Saf, Chr, FF, Op IE, Op Firefox & Opera – use Script DOM Element IE – use document.write Script Tag Safari, Chrome – no benefit; rely on Safari 4 and Chrome 2

EFWS.loadScripts loadScripts: function(aUrls, onload) { // first pass: see if any of the scripts are on a different domain var nUrls = aUrls.length; var bDifferent = false; for ( var i = 0; i < nUrls; i++ ) { if ( EFWS.Script.differentDomain(aUrls[i]) ) { bDifferent = true; break; } // pick the best loading function var loadFunc = EFWS.Script.loadScriptXhrInjection; if ( bDifferent ) { if ( -1 != navigator.userAgent.indexOf('Firefox') || -1 != navigator.userAgent.indexOf('Opera') ) { loadFunc = EFWS.Script.loadScriptDomElement; } else { loadFunc = EFWS.Script.loadScriptDocWrite; } // second pass: load the scripts for ( var i = 0; i < nUrls; i++ ) { loadFunc(aUrls[i], ( i+1 == nUrls ? onload : null ), true); }

multiple scripts with dependencies var aRaceConditions = [['couple-normal.php', 'Normal...]; var aWorkarounds = [['hardcoded-callback.php', 'Hardcod...]; var aMultipleScripts = [['managed-xhr.php', 'Managed XH...]; var aLoadScripts = [['loadscript.php', 'loadScript'],...]; var aSubmenus = [["Race Conditions", aRaceConditions],...]; function init() { EFWS.Menu.createTieredMenu('examplesbtn', aSubmenus); } EFWS.Script.loadScripts(["menu.js", "menutier.js"], init); scripts on same domain: order preserved, no blocking scripts on different domain: order preserved: all loads scripts in parallel: all except Saf3, Chr1 load script and image in parallel: FF, Saf4, Chr2

asynchronous scripts wrap-up Technique Preserve Order Load Scripts in Parallel Load Script & Image in Parallel single script Script DOM Element na all multiple scripts, no dependencies Script DOM Element naall multiple scripts, dependencies, same domain Managed XHRall multiple scripts, dependencies, same domain Script DOM Element (FF, Op), Doc Write (IE, Saf, Chr) all !Saf3, !Chr1 FF, Saf4, Chr2

case study: Google Analytics recommended pattern: 1 var gaJsHost = ((" == document.location.protocol) ? " : " document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); var pageTracker = _gat._getTracker("UA-xxxxxx-x"); pageTracker._trackPageview(); document.write Script Tag approach blocks other resources 1

case study: dojox.analytics.Urchin 1 _loadGA: function(){ var gaHost = (" == document.location.protocol) ? " : " 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) 1

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 multiple interdependent external and inline scripts: much more complex (see hidden slides) concatenate your external scripts into one!

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 best to move inline scripts above stylesheets or below other resources use Link,

eBay MSN MySpace Wikipedia Positioning Inline Scripts

remember inline scripts carry a cost avoid long-executing inline scripts don't put inline scripts between stylesheets and other resources

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"?

news.google.com

downgrading to HTTP/1.0 HTTP/1.1 – 2 connections/server HTTP/1.0 – 4 (IE 6,7), 8 (FF2) HTTP/1.1 has fewer connections because persistent connections are on by default best for static content example:

connections per server by browser newer browsers open more connections* best to shard across 2-4 domains** HTTP/1.1HTTP/1.0 IE 6,724 IE 866 Firefox 1.5, 228 Firefox 366 Safari 3,444 Chrome66 Opera 944 * **

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

flushing and domain blocking you might need to move flushed resources to a domain different from the HTML doc html image script html image script blocked by HTML document different domains

successful flushing Google Search external resource downloaded early content visible to the user google image script image 204

most expensive DOM element blocks parent's onload workaround: set iframe src via setTimeout Using Iframes Sparingly function setSrc() { document.getElementById('if1').src="url"; } setTimeout(setSrc, 0);

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 {}

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. As long as your little subtree continues to check out, the style system will continue moving to the left until it either matches the rule or bails out because of a mismatch." #toc > LI { font-weight: bold; } find every LI whose parent is id="toc" #toc A { color: #444; } find every A and climb its ancestors until id="toc" or DOM root (!) is found

real world levels of CSS # Rules# elements Avg Depth AOL eBay Facebook Google Search Live Search MSN.com MySpace Wikipedia Yahoo! YouTube average

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

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

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

Performance Tools HttpWatch Firebug Page Speed YSlow Smush.it CSS Sprite Generator performance.org/ SpriteMe (in progress) Hammerhead Cuzillion

Performance Analyzers: HPWS rules YSlow Page SpeedPagetestVRTAneXpert combine JS & CSSXXX use CSS spritesXX use a CDNXX set Expires in the futureXXXXX gzip text responsesXXXXX put CSS at the topXX put JS at the bottomX avoid CSS expressionsXX make JS & CSS external reduce DNS lookupsXX minify JSXXX avoid redirectsXXXX remove dupe scriptsX remove ETagsXXX

Performance Analyzers: EFWS rules YSlow Page SpeedPagetestVRTAneXpert don't block UI thread split JS payloadX load scripts async X inline JS b4 stylesheetX write efficient JS min. uncompressed size optimize imagesX X shard domainsX X flush the document avoid iframes simplify CSS selectorsX X

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

Top 10 Performance YSlow Page Speed AOL?*yellow eBay82yellow Facebook68red Google Search95green Live Search93green MSN.com72yellow MySpace84yellow Wikipedia66yellow Yahoo!96yellow YouTube77yellow * YSlow wouldn't start.

Wikipedia combine 6 scripts, 8 stylesheets add Expires header minify JavaScript, save 39K (36%) avoid inline script after stylesheet 31K (41%) unused CSS remove ETags

Yahoo! shard l.yimg.com 46K (49%) unused CSS ~90 very inefficient CSS selectors

1.long HTML doc response 2.flush (good) 3.inline script blocks.js var pageName='HomePagePortal'; 4.scripts block 5.ads.js non-blocking (good) 6.26 bg images – no sprites 7.sharded domains – pics & rtm (good) 8.compress images by 20% 9.thumbs load slowly – HTTP/1.0? 10. remove ETags (?) 11. ~40 inefficient CSS selectors.playgrnd * {}

AOL shard portal.aolcdn.com combine 8 scripts simplify CSS selectors avoid inline script after stylesheet jQueryEnabled = true; remove 97K (49%) unused CSS

Facebook combine 13 scripts, 6 stylesheets sprite 31 background images reduce images by 106K (44%) put stylesheets above scripts remove 102K (50%) unused CSS

MSN.com combine 13 scripts sprite 26 background images put stylesheets above scripts avoid inline script after stylesheet

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

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

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

takeaways focus on the frontend run Page Speed and YSlow speed matters

impact on revenue Google: Yahoo: Amazon: ms -20% traffic ms -5-9% full-page traffic ms -1% sales 1

cost savings hardware – reduced load bandwidth – reduced response size

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

Steve Souders