Data source: Steve Souders Tested on IE6 on Comcast cable modem (~5 mbps) medium powered PC, April 2008.
Ten top sites according to Alexa.com. Data source: Steve Souders Tested on IE6 on Comcast cable modem (~5 mbps) medium powered PC, April 2008. http://www.aol.com/ http://www.ebay.com/ http://www.facebook.com/ http://www.google.com/search?hl=en&q=flowers http://www.myspace.com/ http://www.msn.com/ http://search.live.com/results.aspx?q=flowers&mkt=en-us&scope=&FORM=LIVSOP http://en.wikipedia.org/wiki/Flowers http://www.yahoo.com/ http://www.youtube.com/ For Google and Live Search there are so few components (2-4) and they're mostly cacheable so the HTML document is a bigger percentage.
If you could cut performance in half, FE changes would be 40-45%, while BE would be only 5-10%. BE changes are typically more complex: rearchitecture, optimize code, add/modify hw, distribute databases, etc. FE is simpler: change web server config, place scripts and stylesheets differently in the page, combine requests, etc. I’ve worked with dev teams to cut response times on 50 properties, often by 25% or more. And feedback from other companies is similar. Permission to use photo given by Technicolor: http://flickr.com/photos/technicolor/44988148/
photo courtesy of Vicki & Chuck Rogers: http://www.flickr.com/photos/two-wrongs/205467442/
Data Source: Steve Souders aol 76% ebay 45% facebook 41% google 42% live search 9% msn 37% myspace 37% yahoo 45% youtube 60% wikipedia 26% average 42%
Data source: Steve Souders
Permission to use photo given by Brian.H - http://flickr.com/photos/robinofloxley/750220669/
Of the ten top sites, MSN.com (Script DOM Element), Live Search (Script in Iframe), and Yahoo (Script DOM Element) use advanced script loading techniques.
All of these allow for parallel downloads, but none of them allow for parallel JS execution – that's not possible (currently, WebKit is doing some stuff on that).
Audio (IE "click") is another busy indicator. Delayed rendering and delayed onload ("done") are other busy indicators. Sometimes busy indicators are bad, sometimes good.
Data source: Steve Souders Audio (IE "click") is another busy indicator. Delayed rendering and delayed onload ("done") are other busy indicators. Sometimes busy indicators are bad, sometimes good.
Data source: Steve Souders
I'll do JavaScript and PHP implementations of this logic soon.
Permission to use photo given by Reciprocity: http://flickr.com/photos/alanjaras/76000107/
Data source: Steve Souders
Newer browsers (IE8, Saf4, Chr2) work, but mainstream browsers need a workaround.
putting code in the script block doesn't work in any browser; you have to add stuff to the external script this doesn't load asynchronously
Newer browsers (IE8, Saf4, Chr2) work, but mainstream browsers need a workaround.
Newer browsers (IE8, Saf4, Chr2) work, but mainstream browsers need a workaround.
loadInterval is 420 ms
esp. good when your HTML document takes more than 10-20%, and when users have high latency.
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
14 RULES
MAKE FEWER HTTP REQUESTS
USE A CDN
ADD AN EXPIRES HEADER
GZIP COMPONENTS
PUT STYLESHEETS AT THE TOP
PUT SCRIPTS AT THE BOTTOM
AVOID CSS EXPRESSIONS
MAKE JS AND CSS EXTERNAL
REDUCE DNS LOOKUPS
MINIFY JS
AVOID REDIRECTS
REMOVE DUPLICATE SCRIPTS
CONFIGURE ETAGS
MAKE AJAX CACHEABLE
Sept 2007
June 2009
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
Why focus on JavaScript? AOL eBay Facebook MySpace Wikipedia Yahoo! YouTube
scripts block <script src="A.js"> blocks parallel downloads and rendering 7 secs: IE 8, FF 3.5, Chr 2, Saf 4 9 secs: IE 6-7, FF 3.0, Chr 1, Op 9-10, Saf 3
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 (Page Speed); tools needed to automate this (Microsoft Doloto) load scripts without blocking – how?
MSN.com: parallel scripts 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
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>
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 = 'http://anydomain.com/A.js'; document.getElementsByTagName('head') [0].appendChild(se); script and main page domains can differ no need to refactor JavaScript
Script Defer <script defer src='A.js'></script> supported in IE and FF 3.1+ script and main page domains can differ no need to refactor JavaScript
document.write Script Tag document.write ("<script type='text/javascript' src='A.js'> </script>"); parallelization only works in IE parallel downloads for scripts, nothing else all document.write s must be in same script block
browser busy indicators
browser busy indicators good to show busy indicators when the user needs feedback bad when downloading in the background
ensure/avoid ordered execution
Ensure scripts execute in order:
necessary when scripts have dependencies
IE: http://stevesouders.com/cuzillion/?ex=10017
FF: http://stevesouders.com/cuzillion/?ex=10018
Avoid scripts executing in order:
faster – first script back is executed immediately
http://stevesouders.com/cuzillion/?ex=10019
Load Scripts Without Blocking * 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 order no order no busy show 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
Loading Scripts Without Blocking * 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) * 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
<script type="text/javascript">
var aExamples = [['couple-normal.php', 'Normal Script Src'], ...];
var aExamples = [['couple-normal.php', 'Normal Script Src'], ...];
function init() {
EFWS.Menu.createMenu('examplesbtn', aExamples);
}
init();
</script>
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--; } http://ejohn.org/blog/degrading-script-tags/ cleaner clearer safer – inlined code not called if script fails no browser supports it
technique 4: degrading script tags
<script type="text/javascript">
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") ) {
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;
}
}
}
}
preserves external script order non-blocking works in all browsers couples with inlined code works with scripts across domains ready for this script, eval and call callback bail – need to wait to preserve order if not yet injected
technique 2: DOM Element and Doc Write 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') ||
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!
flushing the document early
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)
call PHP's flush() html image image script html image image script
flushing and domain blocking
you might need to move flushed resources to a domain different from the HTML doc
blocked by HTML document different domains html image image script html image image script
successful flushing
Google Search
external resource downloaded early
content visible to the user
http://www.google.com/images/nav_logo4.png google image image script image 204
performance analyzers (HPWS) YSlow Page Speed Pagetest VRTA neXpert combine JS & CSS X X X use CSS sprites X X use a CDN X X set Expires in the future X X X X X gzip text responses X X X X X put CSS at the top X X put JS at the bottom X avoid CSS expressions X X make JS & CSS external reduce DNS lookups X X minify JS X X X avoid redirects X X X X remove dupe scripts X remove ETags X X X
performance analyzers (EFWS) YSlow Page Speed Pagetest VRTA neXpert don't block UI thread split JS payload X load scripts async X inline JS b4 stylesheet X write efficient JS min. uncompressed size optimize images X X shard domains X X flush the document avoid iframes simplify CSS selectors X X
performance analyzers (other) YSlow Page Speed Pagetest VRTA neXpert use persistent conns X X X reduce cookies 2.0 X X X avoid net congestion X increase MTU, TCP win X avoid server congestion X remove unused CSS X specify image dims X 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
focus on the frontend
run YSlow ( http://developer.yahoo.com/yslow )
and Page Speed! ( http://code.google.com/speed/page-speed/ )
speed matters
takeaways
Bing:
Yahoo:
Google:
AOL:
Shopzilla:
impact on revenue 1 http://en.oreilly.com/velocity2009/public/schedule/detail/8523 2 http://www.slideshare.net/stoyan/yslow-20-presentation 3 http://en.oreilly.com/velocity2009/public/schedule/detail/7579 4 http://en.oreilly.com/velocity2009/public/schedule/detail/7709 +2000 ms -4.3% revenue/user 1 +400 ms -5-9% full-page traffic 2 +400 ms -0.59% searches/user 1 fastest users +50% page views 3 -5000 ms +7-12% revenue 4
0 comments
Post a comment