Steve Souders - PowerPoint PPT Presentation

About This Presentation
Title:

Steve Souders

Description:

none – PowerPoint PPT presentation

Number of Views:31
Avg rating:3.0/5.0
Slides: 57
Provided by: Yah9
Category:
Tags: about | all | souders | steve

less

Transcript and Presenter's Notes

Title: Steve Souders


1
Even Faster Web Sites
  • Steve Souders
  • souders_at_google.com
  • http//stevesouders.com/docs/teched-20090512.ppt

Disclaimer This content does not necessarily
reflect the opinions of my employer.
2
the importance of frontend performance
9
91
17
83
iGoogle, primed cache
iGoogle, empty cache
3
time spent on the frontend
Empty Cache Primed Cache
www.aol.com 97 97
www.ebay.com 95 81
www.facebook.com 95 81
www.google.com/search 47 0
search.live.com/results 67 0
www.msn.com 98 94
www.myspace.com 98 98
en.wikipedia.org/wiki 94 91
www.yahoo.com 97 96
www.youtube.com 98 97
April 2008
4
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
5
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

6
(No Transcript)
7
(No Transcript)
8
(No Transcript)
9
Sept 2007
10
June 2009
11
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
12
Why focus on JavaScript?
13
scripts block
ltscript src"A.js"gt blocks parallel downloads and
rendering
9 secs IE 6-7, FF 3.0, Chr 1, Op 9-10, Saf 3
7 secs IE 8, FF 3.5(?), Chr 2, Saf
4 http//stevesouders.com/cuzillion/?ex10008 What
's Cuzillion?
14
Cuzillion'cuz there are a zillion pages to check
a tool for quickly constructing web pages to see
how components interact Open Source http//steveso
uders.com/cuzillion/
15
initial payload and execution
JavaScript Functions Executed before onload
www.aol.com 115K 30
www.ebay.com 183K 44
www.facebook.com 1088K 9
www.google.com/search 15K 45
search.live.com/results 17K 24
www.msn.com 131K 31
www.myspace.com 297K 18
en.wikipedia.org/wiki 114K 32
www.yahoo.com 321K 13
www.youtube.com 240K 18
26 avg
252K avg
16
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?
17
MSN.com parallel scripts
Scripts and other resources downloaded in
parallel! How? Secret sauce?! var p
g.getElementsByTagName("HEAD")0 var
cg.createElement("script") c.type"text/javascri
pt" c.onreadystatechangen c.onerrorc.onloadk
c.srce p.appendChild(c)
18
Loading Scripts Without Blocking
XHR Eval XHR Injection Script in Iframe Script
DOM Element Script Defer document.write Script Tag
19
XHR Eval
var xhrObj getXHRObject() xhrObj.onreadystatech
ange function() if (
xhrObj.readyState ! 4 ) return
eval(xhrObj.responseText) xhrObj.open('GET',
'A.js', true) xhrObj.send('')
script must have same domain as main page must
refactor script
http//stevesouders.com/cuzillion/?ex10009
20
XHR Injection
var xhrObj getXHRObject() xhrObj.onreadystatech
ange function() if (
xhrObj.readyState ! 4 ) return var
sedocument.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
http//stevesouders.com/cuzillion/?ex10015
21
Script in Iframe
ltiframe src'A.html' width0 height0
frameborder0 idframe1gtlt/iframegt
iframe must have same domain as main page must
refactor script // access iframe from main
page window.frames0.createNewDiv() // access
main page from iframe parent.document.createElemen
t('div')
http//stevesouders.com/cuzillion/?ex10012
22
Script DOM Element
var se document.createElement('script') se.src
'http//anydomain.com/A.js' document.getElement
sByTagName('head') 0.appendChild(se)
script and main page domains can differ no need
to refactor JavaScript
http//stevesouders.com/cuzillion/?ex10010
23
Script Defer
ltscript defer src'A.js'gtlt/scriptgt
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/?ex10013
24
document.write Script Tag
document.write("ltscript type'text/javascript'
src'A.js'gt lt\/scriptgt")
parallelization only works in IE parallel
downloads for scripts, nothing else all
document.writes must be in same script block
http//stevesouders.com/cuzillion/?ex10014
25
browser busy indicators
26
browser busy indicators
status bar progress bar logo cursor block render block onload
normal Script Src FF IE,FF IE,FF FF IE,FF IE,FF
XHR Eval no no no no no no
XHR Injection no no no no no no
Script in Iframe IE,FF FF IE,FF FF no IE,FF
Script DOM Element FF FF FF FF no FF
Script Defer FF FF FF FF FF IE,FF
document.write Script Tag FF IE,FF IE,FF FF IE,FF IE,FF
good to show busy indicators when the user needs
feedback bad when downloading in the background
27
ensure/avoid ordered execution
Ensure scripts execute in order necessary when
scripts have dependencies IE http//stevesouders.
com/cuzillion/?ex10017 FF http//stevesouders.co
m/cuzillion/?ex10018 Avoid scripts executing in
order faster first script back is executed
immediately http//stevesouders.com/cuzillion/?ex
10019
28
Loading Scripts Without Blocking
down-loads domains can differ existing scripts browser busy ensures order size (bytes)
normal Script Src no yes yes IE,FF IE,FF 50
XHR Eval IE,FF no no no no 500
XHR Injection IE,FF no yes no no 500
Script in Iframe IE,FF no no IE,FF no 50
Script DOM Element IE,FF yes yes FF FF 200
Script Defer IE yes yes IE,FF IE 50
document.write Script Tag IE yes yes IE,FF IE 100
Only other document.write scripts are downloaded
in parallel (in the same script block).
29
and the winner is...
30
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?

31
(No Transcript)
32
synchronous JS example menu.js
  • ltscript src"menu.js" type"text/javascript"gtlt/scr
    iptgt
  • ltscript type"text/javascript"gt
  • 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()
  • lt/scriptgt

33
asynchronous JS example menu.js
script DOM element approach
  • ltscript type"text/javascript"gt
  • var domscript document.createElement('script')
  • domscript.src "menu.js"
  • document.getElementsByTagName('head')0.appendChi
    ld(domscript)
  • 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()
  • lt/scriptgt

34
before
after
35
Loading Scripts Without Blocking
down-loads domains can differ existing scripts browser busy ensures order size (bytes)
normal Script Src no yes yes IE,FF IE,FF 50
XHR Eval IE,FF no no no no 500
XHR Injection IE,FF no yes no no 500
Script in Iframe IE,FF no no IE,FF no 50
Script DOM Element IE,FF yes yes FF FF 200
Script Defer IE yes yes IE,FF IE 50
document.write Script Tag IE yes yes IE,FF IE 100
!IE
Only other document.write scripts are downloaded
in parallel (in the same script block).
36
  • what about
  • inlined code
  • that depends on the script?

37
baseline coupling results (not good)
Preserve Execution Order Load Script Image in Parallel
normal Script Src all IE8, Saf4, Chr2
XHR Eval - all
XHR Injection - all
Script in Iframe - all
Script DOM Element FF, Op IE, FF, Saf, Chr
Script Defer FF, Saf, Chr, Op IE, (Saf4, Chr2)
document.write Script Tag all Saf4, Chr2
need a way to load scripts asynchronously AND
preserve order
Scripts download in parallel regardless of the
Defer attribute.
38
coupling techniques
  • hardcoded callback
  • window onload
  • timer
  • degrading script tags
  • script onload

39
technique 1 hardcoded callback
  • ltscript type"text/javascript"gt
  • 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.appendChi
    ld(domscript)
  • lt/scriptgt
  • init() is called from within menu.js
  • not very flexible
  • doesn't work for 3rd party scripts

40
technique 2 window onload
  • ltiframe src"menu.php" width0 height0
    frameborder0gt lt/iframegt
  • ltscript type"text/javascript"gt
  • 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)
  • lt/scriptgt
  • 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

41
technique 3 timer
  • ltscript type"text/javascript"gt
  • var domscript document.createElement('script')
  • domscript.src "menu.js"
  • document.getElementsByTagName('head')0.appendChi
    ld(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)
  • lt/scriptgt
  • load if interval too low, delay if too high

42
John Resig's degrading script tags
  • ltscript src"menu-degrading.js"
    type"text/javascript"gt
  • var aExamples 'couple-normal.php', 'Normal
    Script Src', ...
  • function init()
  • EFWS.Menu.createMenu('examplesbtn', aExamples)
  • init()
  • lt/scriptgt

at the end of menu-degrading.js var scripts
document.getElementsByTagName("script") var cntr
scripts.length while ( cntr ) var
curScript scriptscntr-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
http//ejohn.org/blog/degrading-script-tags/
43
technique 4 degrading script tags
  • ltscript type"text/javascript"gt
  • 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.appendChi
    ld(domscript)
  • lt/scriptgt
  • elegant, flexible (cool!)
  • not well known
  • doesn't work for 3rd party scripts (unless...)

44
technique 5 script onload
  • ltscript type"text/javascript"gt
  • 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.appendChi
    ld(domscript)

45
  • 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

46
multiple script example menutier.js
  • ltscript src"menu.js" type"text/javascript"gtlt/scr
    iptgt
  • ltscript src"menutier.js" type"text/javascript"gtlt
    /scriptgt
  • ltscript type"text/javascript"gt
  • 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)
  • lt/scriptgt

47
technique 1 managed XHR
  • ltscript type"text/javascript"gt
  • 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)
  • lt/scriptgt
  • XHR Injection asynchronous technique does not
    preserve order we have to add that

before
after
48
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.queuedScriptsiQ qScript
  • var xhrObj EFWS.Script.getXHRObject()
  • xhrObj.onreadystatechange function()
  • if ( xhrObj.readyState 4 )
  • if ( bOrder )
  • EFWS.Script.queuedScriptsiQ.response
    xhrObj.responseText
  • EFWS.Script.injectScripts()
  • else
  • eval(xhrObj.responseText)
  • if ( onload )
  • onload()

49
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 lt len i )
  • var qScript EFWS.Script.queuedScriptsi
  • 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
works with scripts across domains
50
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 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
51
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 lt nUrls i )
  • if ( EFWS.Script.differentDomain(aUrlsi) )
  • bDifferent true
  • break
  • // pick the best loading function
  • var loadFunc EFWS.Script.loadScriptXhrInjectio
    n
  • if ( bDifferent )
  • if ( -1 ! navigator.userAgent.indexOf('Firefo
    x')
  • -1 ! navigator.userAgent.indexOf('Opera'
    ) )
  • loadFunc EFWS.Script.loadScriptDomElement
  • else
  • loadFunc EFWS.Script.loadScriptDocWrite

52
multiple scripts with dependencies
  • ltscript type"text/javascript"gt
  • 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)
  • lt/scriptgt
  • 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

53
asynchronous scripts wrap-up
Technique Preserve Order Load Scripts in Parallel Load Script Image in Parallel
single script Script DOM Element na na all
multiple scripts, no dependencies Script DOM Element na all all
multiple scripts, dependencies, same domain Managed XHR all all all
multiple scripts, dependencies, same domain Script DOM Element (FF, Op), Doc Write (IE, Saf, Chr) all !Saf3, !Chr1 FF, Saf4, Chr2
54
case study Google Analytics
  • recommended pattern1
  • ltscript type"text/javascript"gt
  • var gaJsHost (("https" document.location.pro
    tocol) ? "https//ssl." "http//www.")
  • document.write(unescape("3Cscript src'"
    gaJsHost "google-analytics.com/ga.js'
    type'text/javascript'3E3C/script3E"))
  • lt/scriptgt
  • ltscript type"text/javascript"gt
  • var pageTracker _gat._getTracker("UA-xxxxxx-x")
  • pageTracker._trackPageview()
  • lt/scriptgt
  • document.write Script Tag approach blocks other
    resources

1http//www.google.com/support/analytics/bin/answe
r.py?hlenanswer55488
55
case study dojox.analytics.Urchin1
  • _loadGA function()
  • var gaHost ("https" document.location.prot
    ocol) ?
  • "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
56
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!

57
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/?ex10021
  • best to move inline scripts above stylesheets or
    below other resources
  • use Link, not _at_import

58
mispositioned inline scripts
59
Positioning Inline Scripts
remember inline scripts carry a cost avoid
long-executing inline scripts don't put inline
scripts between stylesheets and other resources
60
Simplifying CSS Selectors
  • toc gt LI font-weight bold

61
types of CSS selectors
  • ID selectors
  • toc margin-left 20px
  • element whose ID attribute has the value "toc"
  • class selectors
  • .chapter font-weight bold
  • elements with classchapter
  • type selectors
  • A text-decoration none
  • all A elements in the document tree
  • http//www.w3.org/TR/CSS2/selector.html

62
types of CSS selectors
  • adjacent sibling selectors
  • H1 toc margin-top 40px
  • an element with IDtoc that immediately follows
    an H1
  • child selectors
  • toc gt LI font-weight bold
  • all LI elements whose parent has id"toc"
  • descendant selectors
  • toc A color 444
  • all A elements that have id"toc" as an ancestor

63
types of CSS selectors
  • universal selectors
  • font-family Arial
  • all elements
  • attribute selectors
  • href"index" font-style italic
  • all elements where the href attribute is "index"
  • psuedo classes and elements
  • Ahover text-decoration underline
  • non-DOM behavior
  • others visited, link, active, focus,
    first-child, before, after

64
writing efficient CSS
  • https//developer.mozilla.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. 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 gt 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

65
writing efficient CSS
  • avoid universal selectors
  • don't qualify ID selectors
  • bad DIV navbar
  • good navbar
  • don't qualify class selectors
  • bad LI .tight
  • good .li-tight
  • make rules as specific as possible
  • bad navbar A
  • good .a-navbar

https//developer.mozilla.org/en/Writing_Efficient
_CSS
66
writing efficient CSS
  • avoid descendant selectors
  • bad UL LI A
  • better UL gt LI gt A
  • avoid tag-child selectors
  • bad UL gt LI gt A
  • best .li-anchor
  • be wary of child selectors
  • rely on inheritance
  • http//www.w3.org/TR/CSS21/propidx.html

https//developer.mozilla.org/en/Writing_Efficient
_CSS David Hyatt 4/21/2000
67
Testing CSS Performance
  • 20K TD elements
  • http//jon.sykes.me/152/testing-css-performance-pt
    -2

68
testing massive CSS
  • 20K A elements
  • no style control
  • tag
  • A
  • class
  • .a00001
  • .a20000
  • descender
  • DIV DIV DIV P A.a00001
  • child
  • DIV gt DIV gt DIV gt P gt A.a00001
  • http//jon.sykes.me/153/more-css-performance-testi
    ng-pt-3

69
CSS performance isn't linear
  • IE 7 "cliff" at 18K rules

70
real world levels of CSS
Rules elements Avg Depth
AOL 2289 1628 13
eBay 305 588 14
Facebook 2882 1966 17
Google Search 92 552 8
Live Search 376 449 12
MSN.com 1038 886 11
MySpace 932 444 9
Wikipedia 795 1333 10
Yahoo! 800 564 13
YouTube 821 817 9
average 1033 923 12
71
testing typical CSS
1K rules (vs. 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 A.class0007 ...

http//www.stevesouders.com/blog/2009/03/10/perfor
mance-impact-of-css-selectors/
72
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

73
CSS3 selectors (bad)
  • more David Hyatt
  • "The sad truth about CSS3 selectors is that they
    really shouldnt be used at all if you care about
    page performance. Decorating your markup with
    classes and ids and matching purely on those
    while avoiding all uses of sibling, descendant
    and child selectors will actually make a page
    perform significantly better in all browsers."
  • http//shauninman.com/archive/2008/05/05/css_quali
    fied_selectorscomment_3942

74
selectors to avoid
  • A.class0007 DIV ...
  • id0007 gt A ...
  • .class0007 href ...
  • DIVfirst-child ...

75
reflow time vs. load time
  • reflow time to apply CSS, re-layout elements,
    and repaint
  • triggered by DHTML
  • elem.className "newclass"
  • elem.style.cssText "color red"
  • elem.style.padding "8px"
  • elem.style.display ""
  • reflow can happen multiple times for long-lasting
    Web 2.0 apps

76
reflow time by browser
DHTML action Chr1 Chr2 FF2 FF3 IE6,7 IE 8 Op Saf3 Saf4
className 1x 1x 1x 1x 1x 1x 1x 1x 1x
display none - - - - 1x - - - -
display default 1x 1x 1x 2x 1x 1x - 1x 1x
visibility hidden 1x 1x 1x 1x 1x 1x - 1x 1x
visibility visible 1x 1x 1x 1x 1x 1x - 1x 1x
padding - - 1x 2x 4x 4x - - -
width length - - 1x 2x 1x 1x - 1x -
width percent - - 1x 2x 1x 1x - 1x -
width default 1x - 1x 2x 1x 1x - 1x -
background - - 1x 1x 1x - - - -
font-size 1x 1x 1x 2x 1x 1x - 1x 1x
  • reflow performance varies by browser and action
  • "1x" is 1-6 seconds depending on browser (1K
    rules)

77
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

78
takeaways
  • focus on the frontend
  • run YSlow http//developer.yahoo.com/yslow
  • speed matters

79
impact on revenue
  • Google
  • Yahoo
  • Amazon

500 ms ? -20 traffic1 400 ms ? -5-9 full-page
traffic2 100 ms ? -1 sales1
1 http//home.blarg.net/glinden/StanfordDataMinin
g.2006-11-29.ppt 2 http//www.slideshare.net/stoya
n/yslow-20-presentation
80
cost savings
  • hardware reduced load
  • bandwidth reduced response size

http//billwscott.com/share/presentations/2008/sta
nford/HPWP-RealWorld.pdf
81
  • if you want
  • better user experience
  • more revenue
  • reduced operating expenses
  • the strategy is clear
  • Even Faster Web Sites

82
Steve Souders souders_at_google.com http//stevesoude
rs.com/docs/teched-20090512.ppt
Write a Comment
User Comments (0)
About PowerShow.com