today's class
description
Transcript of today's class
today's classmorning:
how we got hereHTTP overviewHigh Performance Web Sites: Rules 1-6breakexercise: Web 100 statsHigh Performance Web Sites: Rules 7-14
afternoon:morning wrap-upEven Faster Web Sites: chapters 1-4breakEven Faster Web Sites: chapters 5-8exercise: web site performance analysisstate of performance
logisticsslides:
http://stevesouders.com/docs/oreilly-master-class.ppt
install:Firebug - http://getfirebug.com/YSlow - http://developer.yahoo.com/yslow/Hammerhead – http://stevesouders.com/hammerhead/
ask questions!candidate questions appear after each section – if
you can't answer these, ask
how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14
17%
83%
iGoogle, primed cache
the importance of frontend performance
9% 91%
iGoogle, empty cache
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%
14 RULES
1. MAKE FEWER HTTP REQUESTS2. USE A CDN3. ADD AN EXPIRES HEADER4. GZIP COMPONENTS5. PUT STYLESHEETS AT THE TOP6. PUT SCRIPTS AT THE BOTTOM7. AVOID CSS EXPRESSIONS8. MAKE JS AND CSS EXTERNAL9. REDUCE DNS LOOKUPS10.MINIFY JS11.AVOID REDIRECTS12.REMOVE DUPLICATE SCRIPTS13.CONFIGURE ETAGS14.MAKE AJAX CACHEABLE
evangelismConferences
Web 2.0 ExpoThe Ajax ExperienceOSCONGoogle/IOSXSW
CompaniesYahoo!AmazonZillowMicrosoft
ConferencesWordCampFuture of Web AppsWidget SummitVelocityRich Web Experience
AppleNetflixTwitterLinkedIn
GoogleFacebookCBS Interactive
September 2007
how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14
basic HTTP
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1
Request
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 6230
function d(s) {...
Responsestatus code
response headers
request headers
response body
compression
Might want to set Vary:Accept-Encoding and Cache-Control:private
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 6230
function d(s) {...
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflate
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzip
XmoÛHþ\ÿFÖvã*wØoq...
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzip
XmoÛHþ\ÿFÖvã*wØoq...
Expires
Expiration date determines freshness.Can also use Cache-Control: max-age
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflate
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzipExpires: Fri, 26 Sep 2008 22:00:00 GMT
XmoÛHþ\ÿFÖvã*wØoq...
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzipExpires: Fri, 26 Sep 2008 22:00:00 GMT
XmoÛHþ\ÿFÖvã*wØoq...
HTTP/1.1 304 Not Modified
Conditional GET (IMS)
IMS determines validity.IMS is used when Reload is pressed.ETag and If-None-Match also determine validity.
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflate
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflateIf-Modified-Since: Mon, 22 Sep 2008 21:14:35 GMT
sometime after 3pm PT 9/24/08:
questionsWhat are the two key questions when reading
resources from the cache?What is the request header and response header
used to negotiate compression?What are the two response headers you can use
to set an expiration date?What response header provides the file
timestamp of the requested resource?What are the two request headers used to
determine resource validity?
0.9200.515
primed (same session):1 HTTP request, 15 cache reads8Kb xferred0.515 seconds
empty vs. primed cacheempty:30 HTTP requests194Kb xferred3.382 seconds
cache reads
primed (diff session):4 HTTP requests, 28 cache reads13Kb xferred0.920 seconds
0.0 3.382
memory cacheWhy is "primed cache same session" different from "primed cache different session"?Browsers store resources in memory so they don't need to read them from disk.
What determines whether a resource is held in memory cache?I don't know. That'd be a good research project.
disk cacheTwo considerations with disk cache
Is the resource fresh (vs. expired)?If it's expired, is it valid (vs. updated)?
If a resource is fresh, no HTTP request is made – it's just read from disk.
If a resource is expired, a Conditional GET request is made.• If the resource is valid, it's read from disk and the
Conditional GET response is empty.• If the resource has been updated, the Conditional
GET response contains the updated version.
packet sniffersmeasure HTTP requestsHTTPWatch
http://www.httpwatch.com/IE and Firefox, Windows only
Firebug net panelless accurate timings (includes blocking time)
others: AOL Pagetest (web-based), Fiddler (Windows), Wireshark (low-level), IBM Page Detailer (Windows)
FirebugJoe Hewitt, January 2006Firebug Working Group, Mozilla came onboardkit and caboodle:
inspect HTMLCSS explanation and modificationDOM inspectornetwork monitorJavaScript console, log, debugger and profiler
add-on to FirefoxFirebug Lite – bookmarklet for IE, Safari, Opera, etc.
Open Source (free) http://getfirebug.com/
YSlow
YSlowSteve Souders, July 2007web performance analysis tooladd-on to Firebug (extension to an extension)Open Source (free), not open repositoryhttp://developer.yahoo.com/yslow/
questionsWhat's the white space in the HTTP profiles?Why is the HTML document typically not cached?Why are packet sniffers not good for measuring
page load time?
how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14
17%
83%
iGoogle, primed cache
the importance of frontend performance
9% 91%
iGoogle, empty cache
definitionsBackend
Time from when the user makes the request to when the last byte of the HTML document arrives. Includes the time for the initial request to go up, the web server to stitch together the HTML, and for the response to come back.
FrontendShorthand for everything after the HTML document arrives. In reality, includes backend time (primarily reading static files) and network time, as well as true frontend activities such as parsing HTML, CSS, and JS, and executing JS.
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%
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
Rule 1: Make Fewer HTTP Requests
80-90% of load time is the frontendthe frontend time is dominated by HTTPHTTP requests growth since 2003: 25 to 50*
each HTTP request has overhead – even with persistent connections
reducing HTTP requests has the biggest impactbigger benefit for users with higher latencyparallelization reduces the need for this
* http://www.websiteoptimization.com/speed/tweak/average-web-page/
Rule 1: Make Fewer HTTP Requests
But...is it possible to reduce HTTP requests without
reducing richness?Yes:
combine JS, CSSimage mapsCSS spritesinline images
combine JS and CSSnot combining scripts with stylesheetsmultiple scripts => one scriptmultiple stylesheets => one stylesheetapache module:
http://code.google.com/p/modconcat/
YUI Combo Handlerhttp://yuiblog.com/blog/2008/07/16/combohandler/
http://stevesouders.com/examples/combo.php
image maps<img usemap="#map1" border=0 src="/images/imagemap.gif"><map name="map1"> <area shape="rect" coords="0,0,31,31" href="home.html"> <area shape="rect" coords="36,0,66,31" href="gifts.html"> <area shape="rect" coords="71,0,101,31" href="cart.html"> <area shape="rect" coords="106,0,136,31" href="settings.html"> <area shape="rect" coords="141,0,171,31" href="help.html"></map>
old school, CSS sprites is preferredimage maps still useful when x,y coordinates are
useful, for example, in maps
http://stevesouders.com/examples/imagemap.php
CSS spritesmultiple CSS background images => one image<div style="background-image:url('a_lot_of_sprites.gif');background-position: -260px -90px; width: 26px; height: 24px;"></div>
overall size reducedgenerator: http://spritegen.website-performance.org/
http://stevesouders.com/examples/sprites.php
inline images (data: URLs)embed the content of an HTTP response in place
of a URL<IMG ALT="Red Star" SRC="data:image/gif;base64,R0lGODl...wAIlEEADs=">
if embedded in HTML document, probably not cached => embed in stylesheet instead
base64 encoding increases total sizeworks in IE8 (not IE7 and earlier)
http://stevesouders.com/examples/inline-images.php
data: URLsnot just for imagesHammerhead:<frame src="data:text/html,%3Chtml%3E%3Cbody%20style%3D%22background..."></frame>
Rule 2: Use a CDNContent Delivery Networkgeographically distributed servers => closer to your
usersalso: backups, storage, caching, absorb spikesAkamai, Mirror Image, Limelight, Savvisnew: Amazon S3, Panther Express (more affordable)dynamic content: 1 HTTP requeststatic content: all the restdistribute your static content before distributing your
dynamic content
CDN – reverse proxy
Edge Servers
Origin Server(s)
DeveloperUser
name server
ISP's DNS Resolver
198.87.82.45
198.87.82.45
198.87.82.45
CDN
CDN usage
CDNwww.aol.com Akamaiwww.ebay.com Akamaiwww.facebook.com Akamaiwww.google.com/searchsearch.live.com/results Akamaiwww.msn.comwww.myspace.com Akamaien.wikipedia.org/wikiwww.yahoo.comwww.youtube.com
questionsWhat's the most important requirement for a
CDN?How can you find out which CDN a company
uses?What plays the key role in sending users to the
appropriate edge server?
Rule 3: Add an Expires Header
Expiration date determines freshness.Can also use Cache-Control: max-age
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflate
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzipExpires: Mon, 12 Oct 2009 14:57:34 GMTCache-Control: max-age=31536000
XmoÛHþ\ÿFÖvã*wØoq...
Expires vs. max-ageExpires works in HTTP/1.0, max-age in HTTP/1.1Expires is an absolute date:
12 Oct 2009 14:57:34 GMT
max-age is # of seconds until expiration:31536000
Expires relies on clock synchronization between client and server for short expirations
max-age takes precedence over Expires
sending Expires (Apache)mod_expires
<FilesMatch "\.(gif|jpg|js|css)$"> ExpiresDefault "access plus 1 year"</FilesMatch>
sends both Expires and max-age:Expires: Mon, 12 Oct 2009 14:57:34 GMTCache-Control: max-age=315360000
Expires in the wild – 2007Imag
esScrip
tsStyleshee
ts
% with Expir
es
Median Age
amazon.com 0/62 0/3 0/1 0% 114 days
aol.com 23/43 6/18 1/1 48% 217 days
cnn.com 0/138 2/11 0/2 1% 227 days
ebay.com 16/20 0/7 0/2 55% 140 days
froogle.google.com 1/23 0/1 0/1 4% 454 days
msn.com 32/35 3/9 1/1 80% 34 daysmyspace.com 0/18 0/2 0/2 0% 1 daywikipedia.org 6/8 2/3 1/1 75% 1 dayyahoo.com 23/23 4/4 1/1 100% nayoutube.com 0/32 0/7 0/3 0% 26 days
average 10/40 (25%)
2/5 (38%)
0.5/2 (27%)
12/46 (26%)
March 2007
Expires in the wild – 2008Imag
esScrip
tsStyleshee
ts
% with Expir
es
Median Age
aol.com 26/35 13/20 1/1 71% 189 days
ebay.com 48/48 6/7 2/2 98% 1 dayfacebook.com 93/97 20/22 20/20 96% 121
daysgoogle.com/search 1/1 0/1 0/0 50% 1 daysearch.live.com/results 6/6 1/1 4/4 100% namsn.com 45/45 3/3 3/3 100% namyspace.com 21/21 7/7 4/4 100% naen.wikipedia.org/wiki 7/32 5/5 9/9 46% 310
daysyahoo.com 23/23 4/4 1/1 100% nayoutube.com 8/27 1/1 1/1 34% unk
average 28/34 (83%)
6/7 (85%)
5/5 (100%)
38/45 (85%)
October 2008
revving filenames(really, this is independent of Expires headers)once you make a resource public, you can never
change it => aggressive proxies prevent 100% of users from getting the update
best solution: change the filenamedate: trough_062308.gifversion #: onload_1.6.1.jschecksum: 1076572916-dom.common.js
don't use querystring: wikibits.js?179won't be cached by some proxies
questionsWhat's are some differences between Expires
and max-age?What types of resources should an Expires or a
Cache-Control header be used with?Once a resource is cached with a far future
expiration date, how can you push updates and ensure users get the new version?
Rule 4: Gzip Components
typically reduces size by 70%(6230-2066)/6230 = 67%
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 6230
function d(s) {...
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflate
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzip
XmoÛHþ\ÿFÖvã*wØoq...
gzip vs. deflate
gzip (default settings) compresses more
Gzip Deflate
Size SizeSavin
gs SizeSavin
gsScript 3.3K 1.1K 67% 1.1K 66%Script 39.7K 14.5K 64% 16.6K 58%Stylesheet 1.0K 0.4K 56% 0.5K 52%Stylesheet 14.1K 3.7K 73% 4.7K 67%
pros and consPro:
smaller transfer sizeCon:
CPU cycles – on client and server
Don't compress resources < 1K
gzip configurationApache 1.3: mod_gzip
mod_gzip_item_include file \.html$mod_gzip_item_include mime ^text/html$mod_gzip_item_include file \.js$mod_gzip_item_include mime ^application/x-javascript$
mod_gzip_item_include file \.css$mod_gzip_item_include mime ^text/css$
Apache 2.x: mod_deflateAddOutputFilterByType DEFLATE text/html text/css application/x-javascript
control compression level: DeflateCompressionLevelhttp://httpd.apache.org/docs/2.0/mod/mod_deflate.html
HTML Scripts Stylesheetsamazon.com xaol.com x some somecnn.comebay.com xfroogle.google.com x x xmsn.com x deflate deflatemyspace.com x x xwikipedia.org x x xyahoo.com x x xyoutube.com x some some
gzip: not just for HTMLHTML Scripts Stylesheets
aol.com x x xebay.com x somefacebook.com x x xgoogle.com/search x x nasearch.live.com/results
x x x
msn.com x x xmyspace.com x x xen.wikipedia.org/wiki x some someyahoo.com x x xyoutube.com x x xgzip scripts, stylesheets, XML, JSON
(not images, Flash, PDF) March 2007October 2008
edge case: proxiesProxy Origin Server
6 GET main.js (no Accept-Encoding)
2 GET main.js Accept-Encoding: gzip
3 main.js Content-Encoding: gzip
4 main.js Content-Encoding: gzip
5 main.js Content-Encoding: gzip
1 GET main.js Accept-Encoding: gzip
7 main.js Content-Encoding: gzip
proxies may serve gzipped content to browsers that don't support it, and vice versa
edge case: proxies w/ VaryProxy Origin Server
6 GET main.js (no Accept-Encoding)
2 GET main.js Accept-Encoding: gzip
3 main.js Content-Encoding: gzip Vary: Accept-Encoding
4 main.js Content-Encoding: gzip [Accept-Encoding: gzip]
5 main.js Content-Encoding: gzip
1 GET main.js Accept-Encoding: gzip
10 main.js (no gzip)
7 GET main.js (no Accept-Encoding)
9 main.js [Accept-Encoding: ]
8 main.js Vary: Accept-Encoding
11 GET main.js Accept-Encoding: gzip
12 main.js Content-Encoding: gzip
13 GET main.js (no Accept-Encoding)
14 main.js (no gzip) add Vary: Accept-Encoding
edge case: bad browsers< 1% of browsers have problems with gzip
IE 5.5: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q313712
IE 6.0: http://support.microsoft.com/default.aspx?scid=kb;en-us;Q31249
Netscape 3.x, 4.x http://www.schroepl.net/projekte/mod_gzip/browser.htm
User-Agent white list for gzipApache 1.3: mod_gzip_item_include reqheader "User-Agent: MSIE [6-9]" mod_gzip_item_include reqheader "User-Agent: Mozilla/[5-9]"
Apache 2.0: BrowserMatch ^MSIE [6-9] gzip BrowserMatch ^Mozilla/[5-9] gzip
edge case: bad browsers(cont'd)proxies could mix-up responses
give cached response from useragent1 to useragent2
could add Vary: User-Agentso many possibilities, defeats proxy caching
better to add Cache-Control: Private downside: disables all proxy caches
is it a serious problem?hard to diagnose; problem getting smaller
edge case: ETagswhat happens when proxy makes Conditional
GET requests?Last-Modified date for gzipped vs. ungzipped is
different => If-Modified-Since works fineETag is the same in Apache for gzipped &
ungzipped => If-None-Match succeeds, proxy could give browser mismatched content
remove Etags! (Rule 13)
http://issues.apache.org/bugzilla/show_bug.cgi?id=39727
edge case: ETags presentProxy Origin Server
6 GET main.js (no Accept-Encoding)
2 GET main.js Accept-Encoding: gzip
3 main.js Content-Encoding: gzip Cache-Control: max-age=0 ETag: "de158-e58-c7ee4140"
4 main.js Content-Encoding: gzip Cache-Control: max-age=0 ETag: "de158-e58-c7ee4140"
5 main.js Content-Encoding: gzip
1 GET main.js Accept-Encoding: gzip
7 GET main.js If-None-Match: "de158-e58-c7ee4140"
8 304 Not Modified9 main.js Content-Encoding: gzip
proxy gives browser mismatched content
edge case: ETags removedProxy Origin Server
6 GET main.js (no Accept-Encoding)
2 GET main.js Accept-Encoding: gzip
3 main.js Content-Encoding: gzip Cache-Control: max-age=0 Last-Modified: Thu, 21 Aug
2008 23:53:57 GMT
4 main.js Content-Encoding: gzip Cache-Control: max-age=0 Last-Modified: Thu, 21 Aug 2008 23:53:57 GMT
5 main.js Content-Encoding: gzip
1 GET main.js Accept-Encoding: gzip
7 GET main.js If-Modified-Since: Thu, 21 Aug 2008 23:53:57
GMT
8 main.js Cache-Control: max-age=0 Last-Modified: Fri, 22 Aug
2008 09:43:15 GMT
removing ETags avoids the problem
10 main.js (no gzip)
9 main.js Cache-Control: max-age=0 Last-Modified: Fri, 22 Aug 2008 09:43:15 GMT
edge case fixesVary: Accept-
EncodingCache-Control:
privateETag
aol.com xebay.com x x x (IIS)facebook.com xgoogle.com/search xsearch.live.com/results
x x (IIS)
msn.com x (IIS)myspace.com x x (Apa)en.wikipedia.org/wiki x (Apa)yahoo.com xyoutube.com x someVary: User-Agent – not used March 2007October 2008
questionsHow much are file sizes typically reduced by using
gzip compression?What types of resources (images, scripts, etc.)
should not be compressed?For the resource types that should be
compressed, should they always be compressed?
How do you prevent proxies from serving gzipped resources to browsers that don't support gzip?
How can ETags cause proxies to serve mismatched content to browsers?
Rule 5: Put Stylesheets at the Topprogress indicators:*
• reassure the system is working• convey how much time is left• provide something to look at
the web page is the progress indicatorprogressive rendering – draw content as soon as
it's availablestylesheets block progressive rendering in IE,
and cause "flash" in FirefoxDavid Hyatt talks about how browsers work:
http://weblogs.mozillazine.org/hyatt/archives/2004_05.html#005496*Jakob Nielson, http://www.useit.com/papers/responsetime.html
stylesheets in IEin IE, nothing in the page is drawn until all
stylesheets are done downloadingreasoning: parse all rules before drawing any
element, avoids having to redrawwhen stylesheets are at the bottom, there is no
progressive rendering => after a long delay the entire page blasts onto the screen
http://stevesouders.com/examples/css-fouc.php
IE: fastest feels slowest......and slowest feels fastest
stylesheet at bottom: content finishes downloading sooner, but rendering starts later
=> feels slower
stylesheet at top: content finishes downloading later, but rendering starts sooner
=> feels fastertrue in IE 6, 7, 8
stylesheets in Firefoxin Firefox, elements are drawn even if
stylesheets aren't all downloadedreasoning: progressive rendering makes the
page feel faster (most developers will follow the spec and put their stylesheets in HEAD?)
when stylesheets are at the bottom and they change style of rendered elements, elements have to be redrawn => flash of unstyled content
http://stevesouders.com/examples/css-fouc.php
FF2: stylesheets block
stylesheets block downloads in Firefox 2
fixed in Firefox 3
IE 6,7 and mime filters
mime filter plug-ins alter behavior for specific mime types
in IE 6,7 mime filters can affect performance
resource.cgiformerly sleep.cgihttp://stevesouders.com/bin/resource.cgi
• ?type=[gif|js|css|html|swf]• &sleep=n – number of seconds• &expires=[-1|0|1] – sets Expires header in the
past (-1), future (1), or none (0)
useful in exaggerating load times making it possible to observe browser behavior
questionsWhat is progressive rendering? How do stylesheets affect progressive rendering
in IE? in Firefox? Why do they take different approaches?
What's the best way to avoid these problems?
parallelization is an opportunity for improving load times
Rule 6: Put Scripts at the Bottomunfortunately, scripts block in two ways
• downloading resources below the script• rendering elements below the script
http://stevesouders.com/hpws/js-middle.php
moving the scripts lower means less blocking
challengesdocument.write
• scripts that perform document.write must be placed where the content is to be inserted
• alternative: set element.innerHTMLads
• ads typically are at the top of the page and include scripts
• alternative: use iframes or lazy-load adscode dependencies
• some JavaScript must occur higher in the page, and it depends on other scripts
• alternative: move scripts as low as possible, combine them
parallel script loadingexecute scripts in order, but download them in
parallel with other resourcesavailable in IE8, Safari 4, Chrome 2coming in Firefox 3.5IE6&7 will be around for years, we have to keep
them in mind, so…
put scripts at the bottom
questionsHow many connections per hostname is
suggested in the HTTP/1.1 spec?Do all browsers follow this recommendation?What's domain sharding?In what way do scripts block a web page?Give a situation where you can't just move a
script to the bottom of the page.Which browsers support parallel script loading?
how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14
how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14
exercise: Web 100 statshttp://spreadsheets.google.com/ccc?key=pFI0gp5Gg0kHISKLVMRP9cQ
1.pick two web sites2.put your name in "reviewer name" column (each
web site has two reviewers)3.use Hammerhead to measure total load time
(columns B & C)4.use YSlow to measure the rest5. if you're the last one finished with a web site and
your stats are very different, find the other reviewer and try to resolve
how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14
Rule 7: Avoid CSS Expressionsused to set CSS properties dynamically in IE 5-7fixes IE CSS 2.1 bugs and shortcomings, such as
lack of support for min-widthmin-width: 600px;width: expression( document.body.clientWidth < 600 ? “600px” : “auto” );
problem: expressions execute 1000s of timesmouse move, key press, resize, scroll, etc.
http://stevesouders.com/hpws/expression-counter.php (IE only!)
expression's JavaScript can slow down pages
alternatives to expressionsexpressions are evaluated all the time (mouse
move, etc.), this is what makes them easy but slow
alternatives are more work, but reduce the amount of JavaScript code executed
alternatives:• one-time expressions• event handlers
one-time expressionsif an expression only needs to be calculated once, it can overwrite itself with the value
<style>#maindiv { min-width: 600px; width: expression(setW(this));}</style><script type="text/javascript">function setW(elem) { elem.style.runtimeStyle.width = ( document.body.clientWidth < 600 ? "600px" : "auto" );}</script>
doesn't handle window resizing
overwrite the expression
event handlerstie the code to the specific event(s) of interest
<style>#maindiv { min-width: 600px; width: expression(setW(this));}</style><script type="text/javascript">function setW() { elem=document.getElementById('maindiv'); elem.style.runtimeStyle.width = ( document.body.clientWidth < 600 ? "600px" : "auto" );}window.onresize = setW;</script>
Expressions in IE8expressions are no longer supported in IE8
standards modereasons:
• standards compliance – issues fixed in IE8• performance• security – "reduce browser attack surface"
http://blogs.msdn.com/ie/archive/2008/10/16/ending-expressions.aspx
but we'll still need to deal with IE6&7 for years to come
questionsHow do CSS expressions affect performance?What are two workarounds to this problem with
CSS expressions?
Rule 8: Make JS and CSS ExternalBrowser Cache Expt:
how much are resources cached?http://yuiblog.com/blog/2007/01/04/performance-research-
part-2/
add transparent pixel image:<img src="image/blank.gif" height=1 width=1/>
with specific headers:Expires: Thu, 15 Apr 2004 20:00:00 GMTLast-Modified: Wed, 22 Oct 2008 23:49:57 GMT
requests from the browser will have one of these response status codes:200 – the browser does not have the image in its cache304 – the browser has the image in its cache, but needs to
verify the last modified date
desired metrics
What percentage of users view with an empty cache?
# unique users with at least one 200 response
total # unique users
What percentage of page views are done with an empty cache?
total # of 200 responses# of 200 + # of 304
responses
cache results
40-60% of users/day visit with an empty cache75-85% of page views/day are primed cache
0.0%
10.0%
20.0%
30.0%
40.0%
50.0%
60.0%
70.0%
80.0%
90.0%
100.0%
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
day of experiment
perc
enta
ge
unique users with empty cache
page views with empty cache
inline or external?<script type='text/javascript'>var favNumber = 128;</script>
OR <script type='text/javascript' src='fav.js'></script>
<style>#favNumber { font-weight: bold; }</style>
OR <link rel='stylesheet' type='text/css' href='fav.css'>
doc size, # requests, cache
inline
html 20Kcss 10Kjs 20K
png 10Kpng 10K
png 10Kpng 10K
html 50K
external
html 20Kcss 10Kjs 20K
png 10Kpng 10K
png 10Kpng 10K
html 50K
read from cache
empty cache primed cache
3 requests70Kfaster
5 requests70Kslower
1 request50Kslower
1 request20Kfaster
inline or external?inline: faster, but HTML document is biggerexternal: more HTTP requests, but cachedvariables
• page views per user (per session) , external • empty cache stats , external • component re-use across pages , external
external is typically bettermain exception: home pagesbest of both worlds
• post-onload download• dynamic inlining
post-onload downloadinline in front pagedownload external files after onload
window.onload = downloadComponents;function downloadComponents() { var elem = document.createElement("script"); elem.src = "http://.../file1.js"; var head = document.getElementsByTagName('head')[0]; head.appendChild(elem); ...}
speeds up secondary pages
dynamic inliningstart with post-onload downloadset cookie after components downloadedserver-side:
• if cookie, use external• else, do inline with post-onload download
cookie expiration date is keyspeeds up initial and secondary pages
module boundariesfewer files are better – combine JS across all pages
into one script? all CSS into one stylesheet?too much combining – a single page downloads
more than it needscompromise
• define a few page "types", build JS and CSS modules for each page type
• define DHTML components, build JS and CSS modules for each component
optimization – lazy-load modules for other pages from the landing page
questionsWhat's a 200 status code? 304?If 40-60% of users come in with an empty cache once
per day, why are only 15-25% of page views done with an empty cache?
What's typically better, inlining or external?What are three variables to consider?Why are home pages the most likely candidates for
inlining JS and CSS?
Rule 9: Reduce DNS Lookupstypically take 20-100ms, sometimes > 500msOS and browsers cache DNS resolutions
viewing DNSin Windows C:\>ipconfig /flushdns Windows IP Configuration Successfully flushed the DNS Resolver Cache. C:\>ipconfig /displaydns Windows IP Configuration www.google.com ---------------------------------------- Record Name . . . . . : www.google.com Record Type . . . . . : 5 Time To Live . . . . : 43 Data Length . . . . . : 4 Section . . . . . . . : Answer CNAME Record . . . . : www.l.google.com
TTL < 30 minutes might not impact users
TTL (Time to Live)www.amazon.com 1 minutewww.aol.com 1 minutewww.cnn.com 10 minuteswww.ebay.com 1 hourwww.google.com 5 minuteswww.msn.com 5 minuteswww.myspace.com 1 hourwww.wikipedia.org 1 hourwww.yahoo.com 1 minutewww.youtube.com 5 minutes
March 2007
browser DNS cacheIE 7
• DnsCacheTimeout: 30 minutes• KeepAliveTimeout: 1 minute• ServerInfoTimeout: 2 minutes
Firefox 2• network.dnsCacheExpiration: 1 minute• network.dnsCacheEntries: 20• network.http.keep-alive.timeout: 5 minutes• Fasterfox: 1 hour, 512 entries, 30 seconds
Reducing DNS Lookupsuse Keep-Aliveadding DNS lookups vs. domain shardingidentify dominant domain names, reduce non-
dominant namesfor dominant domains – shard across 2-4
CNAMEs
questionsHow long does a DNS lookup typically take?What are three places where DNS resolutions are
cached?What's a TTL? How do OSes and browsers (not)
honor TTLs?What's the guideline for balancing DNS lookups
and domain sharding?
Rule 10: Minify JavaScriptminification: removing unnecessary characters
from code (comments, white space, etc.)obfuscation: minify as well as reduce length of
symbol names (munge)
original codeYAHOO.util.CustomEvent = function(type, oScope, silent, signature) { this.type = type; this.scope = oScope || window; this.silent = silent; this.signature = signature || YAHOO.util.CustomEvent.LIST; this.subscribers = []; if (!this.silent) { } var onsubscribeType = "_YUICEOnSubscribe"; if (type !== onsubscribeType) { this.subscribeEvent = new YAHOO.util.CustomEvent(onsubscribeType, this, true); }};
event.js from YUI – http://developer.yahoo.com/yui/
minified codeYAHOO.util.CustomEvent=function(type,oScope,silent,signature){this.type=type;this.scope=oScope||window;this.silent=silent;this.signature=signature||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var_onsubscribeType="_YUICEOnSubscribe";if(type!==onsubscribeType){this.subscribeEvent=new_YAHOO.util.CustomEvent(onsubscribeType,this,true);}};
JSMinhttp://crockford.com/javascript/jsmin
YUI Compressor http://developer.yahoo.com/yui/compressor/also munges and minifies CSS
obfuscated codeYAHOO.util.CustomEvent=function(_1,_2,_3,_4){this.type=_1;this.scope=_2||window;this.silent=_3;this.signature=_4||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var _5="_YUICEOnSubscribe";if(_1!==_5){this.subscribeEvent=new YAHOO.util.CustomEvent(_5,this,true);}};
DoJo Compressor (ShrinkSafe)http://dojotoolkit.org/docs/shrinksafe/
YUI Compressor http://developer.yahoo.com/yui/compressor/
obfuscation costsobfuscation typically reduces size more, but has
some costs• bugs – symbol munged to "aa", namespace conflict• maintenance – tag external symbols (eg, API)• debugging – harder to read in production
minification vs. obfuscationWeb Site Original
Size After JSMin After ShrinkSafe
amazon.com 204K 173K 156K
aol.com 44K 40K 40K
cnn.com 98K 79K 74K
myspace.com 88K 65K 64K
wikipedia.org 42K 28K 26K
youtube.com 34K 26K 24KAverage 85K 68K (-21%) 64K (-25%)
minify – extra savings from obfuscation is not worth the risk
gzip and minificationWeb Site Original
Size After Gzip JSMIN & Gzip
Shrink-Safe & Gzip
amazon.com 204K 48K 41K 42K
aol.com 44K 16K 15K 15K
cnn.com 98K 29K 23K 23K
myspace.com 88K 23K 19K 19K
wikipedia.org 42K 13K 8K 8K
youtube.com 34K 10K 8K 8KAverage 85K 23K (-73%) 19K (-78%) 19K (-78%)
minify – obfuscation benefits decline with gzip
Top 10 minificationMinify External? Minify Inline?
Apr 07 Oct 08 Apr 07 Oct 08www.amazon.com yeswww.aol.com some mostwww.cnn.comwww.ebay.com yes yes yesfroogle.google.com yes yes yes yeswww.msn.com yes yes yes yeswww.myspace.com somewww.wikipedia.orgwww.yahoo.com yes yes yes yeswww.youtube.com yes
Minifying CSSsavings are typically less compared to JavaScript
• not as much CSS as JavaScript• CSS typically has fewer comments and whitespace
greater savings from CSS optimizations• merging identical rules• abbreviations
"#660066" => "#606""0px" => "0""background-color:" => "background:"
questionsWhat's the difference between minification and
obfuscation?How do they compare wrt reducing JavaScript size?What are three drawbacks to obfuscation?
Rule 11: Avoid Redirects3xx status codes: "further action needs to be taken by the user agent in order to fulfill the request"
300 Multiple Choices (based on Content-Type)301 Moved Permanently302 Moved Temporarily (aka, Found)303 See Other (clarification of 302)304 Not Modified 305 Use Proxy306 (no longer used)307 Temporary Redirect (clarification of 302)
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3
response for conditional GET request
most popular
HTTP/1.1
redirect example
go to the new location instead of the original onewhy use redirects?
prettier URLstrack trafficauthentication
GET / HTTP/1.1Host: astrology.yahoo.com
Request
HTTP/1.1 301 Moved PermanentlyLocation: http://shine.yahoo.com/astrology/
Response
worst blocker
inserting a redirect to the HTML document is worse than how stylesheets and scripts block
all resources in the page are delayedthe user gets very little feedback (nothing in the
page)rendering, even the HTML text, is delayed
2nd worse – redirecting to a script
"Moved Permanently" – is it cached?no
spec: "cacheable if indicated by a Cache-Control or Expires header field"
caching redirects
GET / HTTP/1.1Host: astrology.yahoo.com
Request
HTTP/1.1 301 Moved PermanentlyDate: Tue, 28 Oct 2008 07:39:53 GMTLocation: http://shine.yahoo.com/astrology/Cache-Control: privateConnection: closeTransfer-Encoding: chunkedContent-Type: text/html; charset=utf-8
Response
caching: 301, 302, Expirespast Expires no Expires future Expires
301Moved
Permanently
don't cache:all
don't cache: IE, FF3, Safari, Opera
cache: FF2, Chrome
don't cache: IE, FF3, Safari, Opera
cache: FF2, Chrome
302Moved
Temporarily
don't cache:all
don't cache: IE, FF3, Safari, Opera, Chrome
cache: FF2
don't cache: IE, FF3, Safari, Opera
cache: FF2, Chrome
past Expires no Expires future Expires
301Moved
Permanently
don't cache:all
don't cache: IE, FF3, Safari, Opera
cache: FF2, Chrome
don't cache: IE, FF3*, Safari, Opera
cache: FF2, Chrome
302Moved
Temporarily
don't cache:all
don't cache: IE, FF3, Safari, Opera, Chrome
cache: FF2
don't cache: IE, FF3*, Safari, Opera
cache: FF2, Chrome
FF2 and Chrome – only browsers to cache redirects*Firefox 3.1 fixes regression from FF2 to FF3
redirect alternativesJavaScript
document.location = "destination.php";
what if JavaScript is disabled or not present?
meta refresh – put in document's HEAD<meta http-equiv="refresh" content="0; url=destination.php">
in IE, causes conditional GET requests for all resources (similar to Reload button)
# of seconds
cache workaround<html><head><script type="text/javascript">window.onload = function () { document.location = "destination.php"; }</script><noscript><meta http-equiv="refresh"
content="0; url=destination.php"></noscript></head>
one last thing – make this document cacheable!
need to let the page load so it can be cached
redirects in the top 10
mostly ads
# redirectswww.aol.com 5www.ebay.comwww.facebook.comwww.google.com/searchsearch.live.com/resultswww.msn.com 1www.myspace.comen.wikipedia.org/wikiwww.yahoo.com 2www.youtube.com
common uses1. redirect from blah.com to www.blah.com2. missing trailing slash3. tracking internal traffic4. tracking outbound traffic5. prettier URLs, preserve old URLs6. connecting web sites7. ads8. authentication
avoid redirectseliminate the need
base href or full URLs for resourcesreferer trackingHTML 5 – A ping and LINK pingbackCNAMEsmod_rewriteno autoindex
make them cacheable301 with future ExpiresJavaScript & meta refresh with future Expires
questionsWhat's the status text for 301 and 302?What HTTP response header contains the URL the user is
redirected to?Why are redirects worse than stylesheets and scripts in
terms of blocking?If a redirect is "Moved Permanently", does that mean it's
cached?Which browsers today cache redirects? What are two other techniques for doing redirects? How
can they be used to make redirects cacheable?
Rule 12: Remove Duplicate Scriptshurts performance
• extra HTTP requests if not cacheablehttp://stevesouders.com/hpws/dupe-scripts.phpIE and FF
• extra executionshttp://stevesouders.com/hpws/dupe-scripts-cached10.phpall browsers
atypical?• happens with ads
http://www.aol.com/adsonar.js (6K) loaded six times
• happens with iframeshttp://www.ossamples.com/recipes/fc-os-ext.js (15K), gadgets_en.js (155K) each loaded 3 times
script insertion Functions
<?phpfunction insertScript($jsfile) { if ( alreadyInserted($jsfile) ) { return; }
pushInserted($jsfile);
if ( hasDependencies($jsfile) ) { $dependencies = getDependencies($jsfile); for ( $i = 0; $i < count($dependencies); $i++ ) { insertScript($dependencies[$i]); } }
echo '<script type="text/javascript" src="' . getVersion($jsfile) . '"></script>";}?>
questionsWhat are two typical causes of duplicate scripts?
In what way(s) can duplicate scripts be bad for performance?
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzip
XmoÛHþ\ÿFÖvã*wØoq...
Rule 13: Configure ETags
expiration date determines freshnesscan also use Cache-Control:max-age
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflate
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzipExpires: Fri, 26 Sep 2008 22:00:00 GMT
XmoÛHþ\ÿFÖvã*wØoq...
Expires and Last-Modified
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflateIf-Modified-Since: Mon, 22 Sep 2008 21:14:35 GMT
HTTP/1.1 304 Not Modified
Conditional GET (IMS)
IMS determines validity – does the browser's cached version match what's on the server?
the comparison is based on the resource's datea 304 response is sent instead of all the dataIMS is used when Reload is pressed
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzip
XmoÛHþ\ÿFÖvã*wØoq...
ETag response header
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflate
HTTP/1.1 200 OKContent-Type: application/x-javascriptLast-Modified: Mon, 22 Sep 2008 21:14:35 GMTContent-Length: 2066Content-Encoding: gzipExpires: Fri, 26 Sep 2008 22:00:00 GMTETag: "19f1e-7920-4525b037f0440"
XmoÛHþ\ÿFÖvã*wØoq...
GET /v-app/scripts/107652916-dom.common.js HTTP/1.1Host: www.blogger.comUser-Agent: Mozilla/5.0 (…) Gecko/2008070208 Firefox/3.0.1Accept-Encoding: gzip,deflateIf-Modified-Since: Mon, 22 Sep 2008 21:14:35 GMTIf-None-Match: "19f1e-7920-4525b037f0440"
HTTP/1.1 304 Not Modified
Conditional GET (INM)
alternative way to test validity
what is an ETag?http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11
added in HTTP/1.1used by clients and servers to validate expired
resourcesmore flexible than Last-Modified date"An entity tag consists of an opaque quoted
string"" An entity tag MUST be unique across all versions
of all entities associated with a particular resource."
If-None-Match (hit)
"If any of the entity tags match the entity tag of the entity that would have been returned in the response to a similar GET request (without the If-None-Match header) on that resource[…], then the server MUST NOT perform the requested method, unless required to do so because the resource's modification date fails to match that supplied in an If-Modified-Since header field in the request. Instead, if the request method was GET or HEAD, the server SHOULD respond with a 304 (Not Modified) response,…"
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
INM, IMS hit & miss
hit miss
hit 304 full response
miss
If-Modified- Since
If-None-Match
If-None-Match (miss)If none of the entity tags match, then the server
MAY perform the requested method as if the If-None-Match header field did not exist, but MUST also ignore any If-Modified-Since header field(s) in the request. That is, if no entity tags match, then the server MUST NOT return a 304 (Not Modified) response.
INM, IMS hit & miss
hit miss
hit 304 full response
miss full response full response
If-Modified- Since
If-None-Match
if not managed properly, sending both IMS and INM lowers the chances of a simple, small 304 response
How could it not be managed properly?!
Apache ETags"19f1e-7920-4525b037f0440""inode-size-timestamp"inode – used by filesystems to store file type,
owner, group, permissions, etc.inode for the same file differs across servers
even if file size, timestamp, and directory is the same
http://stevesouders.com/images/arrow-right-9x13.pngETag: "21f5315-d4-5d51f0c0"
http://1.cuzillion.com/images/arrow-right-9x13.pngETag: "1ee57ec-d4-5d51f0c0"
IIS ETags"b4f35327edac51:113f""timestamp:changenumber"changenumber – counter to track IIS
configuration changeschangenumber rarely the same across servershttp://hp.msn.com/global/c/hpv10/favicon.ico
ETag: "b4f35327edac51:113f"ETag: "b4f35327edac51:e6e"
example ETag missGET /global/c/hpv10/favicon.ico HTTP/1.1Host: hp.msn.comIf-Modified-Since: Wed, 26 Oct 2005 22:39:58 GMTIf-None-Match: "b4f35327edac51:19bc"
HTTP/1.x 200 OKContent-Length: 1406Etag: "b4f35327edac51:d76"Last-Modified: Wed, 26 Oct 2005 22:39:58 GMTExpires: Wed, 06 Feb 2008 01:10:16 GMT
timestamp is the sameLast-Modified matches (but IMS misses)
changenumber differs, validations misses, entire body is resentvalidation miss
the problem with ETagsthe default ETag syntax in Apache and IIS makes
it unlikely that INM will match across servers, even when the resource is the same
probability of an incorrect INM miss:(n-1)/n where "n" is the number of serversnot an issue if you just have one server
http://www.apacheweek.com/issues/02-01-18 "can cause an unnecessary performance hit as
resources are fetched more often than is required"
http://support.microsoft.com/kb/922703"IIS 6.0 sends a 200 response because it considers
the different change numbers to mean that [the resources] are not the same versions"
the solution for ETagsif you're not leveraging ETags, turn them offreduces size of requests and responsesreduces outbound traffic from your serversincreases proxy cache hit rateApache:
FileETag noneIIS:
synchronize changenumber across servershttp://support.microsoft.com/kb/922703/
ETags in the wildserver ETag
s?default syntax
?www.aol.com AOLserver no –www.ebay.com IIS yes yeswww.facebook.com Apache no –www.google.com/search
gws no –
search.live.com/results
ASP.NET yes no
www.msn.com IIS no –www.myspace.com Apache some noen.wikipedia.org/wiki Apache
lighthttpdsomeyes
no?
www.yahoo.com YTS no –www.youtube.com btfe no –
possible uses for ETags???
questionsWhy were ETags introduced in HTTP/1.1?What do "IMS" and "INM" stand for?How do IMS and INM interplay during resource
validation?What component in the default ETag syntax hurts
performance in Apache and IIS, and why?What are three performance gains you can
achieve by turning off ETags?
async == instantaneous (?)try Google Maps on dialuppassive Ajax requests
in anticipation of user's needse.g., download address book for webmail
active Ajax requestsin response to user actione.g., email search requestuser is waiting; not instantaneousoptimize these first
Ajax optimizationsadd an Expires headergzip componentsminify JavaScriptavoid redirectsconfigure ETags
most important
cache Ajax? really?!but...
it's dynamicyes, but for this [user | time | browser] it's [always the same | doesn't change for awhile]
it's datasometimes data doesn't change
it's private:no-store doesn't always workshould you use https?
caching XHR vs. HTMLXHR and HTML often contain dynamic,
personalized datawhy can I cache XHR, but not HTML?the URL for HTML is often frozen
• bookmarks• cross-references• prettier• memorized
developers control what's in XHR URLs• the XHR URL is contained inside the HTML• the developer can modify the XHR URL with data
to avoid a cache hit
ex: Google Calendarhttp://www.google.com/calendar/contacts
HTTP/1.x 200 OKCache-Control: no-cache, no-store, max-age=0, must-
revalidatePragma: no-cacheExpires: Fri, 01 Jan 1990 00:00:00 GMTContent-Type: text/javascript; charset=UTF-8Content-Encoding: gzipDate: Mon, 10 Nov 2008 22:00:57 GMTContent-Length: 1562
solution:add modification timestamp to URLhttp://www.google.com/calendar/contacts_1226354800
questionsWhich performance rules so far apply to Ajax?What are passive Ajax requests? active?Why may developers view the cacheability of
Ajax responses differently than other content?If I can cache XHRs, why can't I cache HTML that
also contains dynamic data?
LUNCH!
morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance
morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance
September 2007
June 2009
Even Faster Web Sites
Splitting the initial payloadLoading scripts without blockingCoupling asynchronous scriptsPositioning inline scriptsSharding dominant domainsFlushing the document earlyUsing iframes sparinglySimplifying CSS Selectors
Understanding Ajax performanceDoug Crockford
Writing efficient JavaScript Nicholas Zakas
Creating responsive web apps Ben Galbraith, Dion Almaer
Scaling with CometDylan Schiemann
Going Beyond GzippingTony Gentilcore
Optimizing Images Stoyan Stefanov, Nicole Sullivan
AOLeBayFacebookMySpaceWikipediaYahoo!
why focus on JavaScript?
YouTube
scripts block
<script src="A.js"> blocks parallel downloads and rendering
http://stevesouders.com/cuzillion/?ex=10008
a tool for quickly constructing web pages to see how components interact
Open Sourcehttp://stevesouders.com/cuzillion/
Cuzillion'cuz there are a zillion pages to check
JavaScript
Functions Executed before
onloadwww.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% avg252K avg
initial payload and execution
the other 74%what's the other ~74% of JavaScript for?
• conditional blocks – errors, specific browsers, edge cases
• DHTML features – dynamic menus, popup DIVs, XHR
• cruft!
given the blocking nature of JavaScript, it's painful to slowdown the page for JavaScript that may never be used
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?
questionsWhat's the average size of JavaScript
downloaded by the Alexa top ten? On average how much of that is executed before onload?
Why is this measurement done at the onload event?
Why is there so much JavaScript that's not called before onload?
What does "lazy load" mean? How do you lazy load a script?
MSNScripts 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 pagemust refactor script
var xhrObj = getXHRObject();xhrObj.onreadystatechange = function() { if ( xhrObj.readyState != 4 ) return; eval(xhrObj.responseText); };xhrObj.open('GET', 'A.js', true);xhrObj.send('');
http://stevesouders.com/cuzillion/?ex=10009
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 pagehttp://stevesouders.com/cuzillion/?ex=10015
Script in Iframe
<iframe src='A.html' width=0 height=0 frameborder=0 id=frame1></iframe>
iframe must have same domain as main pagemust refactor script:
// access iframe from main pagewindow.frames[0].createNewDiv();
// access main page from iframeparent.document.createElement('div');
http://stevesouders.com/cuzillion/?ex=10012
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 differno need to refactor JavaScript
http://stevesouders.com/cuzillion/?ex=10010
Script Defer
<script defer src='A.js'></script>
only supported in IE (just landed in FF 3.1)script and main page domains can differno need to refactor JavaScript
http://stevesouders.com/cuzillion/?ex=10013
document.write Script Tag
document.write("<script type='text/javascript' src='A.js'> <\/script>");
parallelization only works in IEparallel downloads for scripts, nothing elseall document.writes must be in same script
block
http://stevesouders.com/cuzillion/?ex=10014
browser busy indicators
browser busy indicators
good to show busy indicators when the user needs feedbackbad when downloading in the background
Ensure scripts execute in order:necessary when scripts have dependenciesIE: http://stevesouders.com/cuzillion/?ex=10017
FF: http://stevesouders.com/cuzillion/?ex=10018
Avoid scripts executing in order:faster – first script back is executed immediatelyhttp://stevesouders.com/cuzillion/?ex=10019
ensure/avoid ordered execution
asynchronous loading traits
*Only other document.write scripts are downloaded in parallel (in the same script block).
and the winner is...XHR EvalXHR InjectionScript in iframeScript DOM ElementScript Defer
Script DOM ElementScript Defer
Script DOM Element
Script DOM Element (FF)Script Defer (IE)
XHR EvalXHR InjectionScript in iframeScript DOM Element (IE)
XHR InjectionXHR EvalScript DOM Element (IE)
Managed XHR InjectionManaged XHR EvalScript DOM Element
Managed XHR InjectionManaged XHR Eval
Script DOM Element (FF)Script Defer (IE)Managed XHR EvalManaged XHR Injection
Script DOM Element (FF)Script Defer (IE)Managed XHR EvalManaged XHR Injection
different domains same domains
no order
preserve order
no order
no busyshow busy
show busyno busy
preserve order
ads and async scriptsmany ads load external scriptswhy can't these scripts be loaded using these
non-blocking techniques?they use document.write
if a script containing document.write is loaded asynchronously, the entire page is erased:http://stevesouders.com/tests/delayed-script-execution.php(click on "Load Dynamically")
an alternative: Opera's "Delayed Script Execution"
Opera delayed scriptsopera:config#Extensions|DelayedScriptExecution
delays (defers) script loading with some nice enhancements• deferred to the very end• remembers script location so document.write still
works
huge improvement for adsprototype for future implementation of defer
http://www.stevesouders.com/blog/2008/09/11/delayed-script-execution-in-opera/
Loading Scripts Without Blockingdon't let scripts block other downloadsyou can still control execution order, busy
indicators, and onload event
what about inlined code dependencies?
questionsIf you could only use one technique, which would
you pick? Why?Why is executing scripts out of order faster?Which of the techniques does block rendering?What happens if an external script loaded
asynchronously does document.write?
synchronous JS example: menu.js
<script src="menu.js" type="text/javascript"></script>
<script type="text/javascript">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>
asynchronous JS example: menu.js
<script type="text/javascript">var domscript = document.createElement('script');domscript.src = "menu.js"; document.getElementsByTagName('head')
[0] .appendChild(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();</script>
script DOM element approach
before
after
asynchronous loading traits
*Only other document.write scripts are downloaded in parallel (in the same script block).
!IE
what about
inlined code that depends on the script?
Coupling Asynchronous Scripts
hardcoded callbackwindow onloadtimerdegrading script tagsscript onload
technique 1: hardcoded callback<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.js";document.getElementsByTagName('head')
[0].appendChild(domscript);</script>
init() is called from within menu.jsnot very flexibledoesn't work for 3rd party scripts
technique 2: window onload<iframe src="menu.php" width=0 height=0 frameborder=0>
</iframe><script type="text/javascript">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);}</script>
init() is called at window onloadmust use async technique that blocks onload:
Script in Iframe does this across most browsersinit() called later than necessary
technique 3: timer<script type="text/javascript">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);</script>
load if interval too low, delay if too highslight increased maintenance – EFWS
John Resig's degrading script tags<script src="menu-degrading.js" type="text/javascript">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/
cleanerclearersafer – inlined code not called if script failsno 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") ) { domscript.innerHTML = "init();";}else { domscript.text = "init();";}document.getElementsByTagName('head')[0].appendChild(domscript);</script>
elegant, flexible (cool!)not well knowndoesn't work for 3rd party scripts (unless...)
technique 5: script onload<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.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);</script>
pretty nice, medium complexity
case study: Google Analytics
recommended pattern:*
<script type="text/javascript">var gaJsHost = (("https:" == document.location.protocol) ?
"https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">var pageTracker = _gat._getTracker("UA-xxxxxx-x");pageTracker._trackPageview();</script>
document.write Script Tag approach blocks other resources
* http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55488
case study: dojox.analytics.Urchin*
_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)* http://docs.dojocampus.org/dojox/analytics/Urchin
asynchronous loading & couplingasync technique: Script DOM Element
easy, cross-browserdoesn't ensure script order
coupling technique: script onloadfairly easy, cross-browserensures execution order for external script and
inlined code
questionsHow can you load an external script
asynchronously, and have an inline script execute as soon as the external script is loaded?
Positioning Inline Scriptslong executing inline scripts block rendering and
downloads of everything after them in the pagehttp://stevesouders.com/cuzillion/?c0=bi1hfff1_0&c1=bb0hfff0_5&c2=bi1hfff1_0
workarounds: •initiate execution with setTimeout (>250 for FF, nglayout.initialpaint.delay)•move JavaScript to external script with advanced downloading techniques•use Defer attribute (IE only)•make code re-entrant, call setTimeout every 300ms
inline script parallelizationresources that occur before an inline script
download in parallel while the script executeshttp://stevesouders.com/cuzillion/?c0=bi1hfff2_0&c1=bb0hfff0_1&c2=bf2hfff2_0&c3=bb0hfff0_1&c4=bi3hfff2_0
...except for stylesheetshttp://stevesouders.com/cuzillion/?c0=bc1hfff2_0&c1=bb0hfff0_1&c2=bc2hfff2_0&c3=bb0hfff0_1&c4=bi3hfff2_0
why?!CSS and JavaScript might have interdependenciesgetElementsByClassName (HTML 5)
how might this affect stylesheet and inline script download parallelization?
stylesheet, inline script block downloading
browsers download stylesheets in parallel with other resources*
...unless the stylesheet is followed by an inline scripthttp://stevesouders.com/cuzillion/?ex=10021
best to move inline scripts above stylesheets or below other resources
* except Firefox 2
eBayMSNMySpaceWikipedia
examples of scattered scripts
Positioning Inline Scripts
remember inline scripts carry a costavoid long-executing inline scriptsdon't put inline scripts between stylesheets and
other resources
questionsWhat do inline scripts block? How can you
workaround this blocking?What's the unusual behaviour of a stylesheet,
inline script, and image (in that order)? What would explain why browser developers implemented this behaviour?
morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance
morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance
HTTP/1.1 and older browsers• 2 connections per server• based on name, not IP• includes IE 6,7
"domain sharding"intentionally splitting resources
across multiple domains
makes pages load faster
Sharding Dominant Domains
Sharding Dominant Domainsbut Rule 9 says "Reduce DNS lookups"?!
remove DNS lookups that aren't heavily usedsplit domains that are on the critical path
how find "critical path"?
www.yahoo.com
http://news.google.com
news.google.com
downgrading to HTTP/1.0HTTP/1.1 – 2 connections/serverHTTP/1.0 – 4 (IE 6,7), 8 (FF2) connsHTTP/1.1 has fewer connections
because persistent connections are on by default
best for static contentexample: http://wikipedia.org/
newer browsers
newer browsers open more connectionshttp://www.stevesouders.com/blog/2008/03/20/roundup-on-
parallel-connections/
HTTP/1.1 HTTP/1.0
IE 6,7 2 4
IE 8 6 6
Firefox 1.5, 2 2 8
Firefox 3 6 6
Safari 3,4 4 4
Chrome 6 ?
Opera 9 4 4
how many domains?http://yuiblog.com/blog/2007/04/11/performance-
research-part-4/
2-4 is optimalafter 4 domains, response time degrades
more DNS lookupsthrashing on client
questionsWhat's "domain sharding"?Why would downgrading to HTTP/1.0 be faster?
Should I do that for all responses?Why would the HTTP/1.1 spec suggest fewer
connections per server?What's the # of connections per server for
popular browsers?What's the optimal number of domains to shard
across?
Flushing the Document Early
start the browser working before the HTML document is even completed
makes sense for pages with long backend time (exceptions to the Performance Golden Rule)
gives users feedback soonerstarts downloads earlier
htmlimageimagescript
htmlimageimagescript call PHP's flush()
where to flush
after a few resourcesafter some content the user will seebefore the backend part that is slow
flushing gotchas
PHP output_buffering – ob_flush()Transfer-Encoding: chunkedgzip – Apache's DeflateBufferSize before 2.2.8proxies and anti-virus softwarebrowsers – IE (255b), 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
htmlimageimagescript
htmlimageimagescript
googleimageimagescriptimage204
case study: Google search
blocked by HTML document
different domains
questionsWhat does it mean to "flush" the document?
Why does this help performance?Where should I put the call to flush() in my
backend code?Will flushing work behind my company proxy?
Using Iframes Sparingly
load 100 empty elements of each type
iframes are 10-100x more expensive
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
<iframe id=iframe1 src=""></iframe><script type="text/javascript">document.getElementById('iframe1').src="url";</script>
scripts block iframe
no surprise – scripts in the parent block the iframe from loading
IE
Firefox
Safari Chrome
Opera
script
script
script
stylesheets block iframe (IE, FF)
surprise – stylesheets in the parent block the iframe or its resources in IE & Firefox
IE
Firefox
Safari Chrome
Opera
stylesheet
stylesheet
stylesheet
stylesheets after iframe still block (FF)
surprise – even moving the stylesheet after the iframe still causes the iframe's resources to be blocked in Firefox
IE
Firefox
Safari Chrome
Opera
stylesheet
stylesheet
stylesheet
iframes: no free connections
iframe shares connection pool with parent (here – 2 connections per server in IE 7)
iframe
parent
questionsWhy are iframes the most expensive DOM
element?Why is the fact that iframes block the onload
event bad?
Simplifying CSS Selectors
#toc > LI { font-weight: bold; }
combinatorsimple selectors
selector
declaration block
rule
http://stevesouders.com/efws/selectors.php
types of CSS selectorsID selectors
#toc { margin-left: 20px; } element whose ID attribute has the value "toc"
class selectors.chapter { font-weight: bold; }elements with class=chapter
type selectorsA { text-decoration: none; }all A elements in the document tree
http://www.w3.org/TR/CSS2/selector.html
types of CSS selectorsadjacent sibling selectors
H1 + #toc { margin-top: 40px; } an element with ID=toc that immediately follows an H1
child selectors#toc > 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
types of CSS selectorsuniversal selectors
* { font-family: Arial; }all elements where the "hidden" attribute is "true"
attribute selectors[href="#index"] { font-style: italic; }all elements where the href attribute is "#index"
psuedo classes and elementsA:hover { text-decoration: underline; }non-DOM behaviorothers: :visited, :link, :active, :focus, :first-child, :before, :after
writing efficient CSShttps://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 > 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
writing efficient CSS1. avoid universal selectors2. don't qualify ID selectors
• bad: DIV #navbar {}• good: #navbar {}
3. don't qualify class selectors• bad: LI .tight {}• good: .li-tight {}
4. make rules as specific as possible• bad: #navbar A {}• good: .a-navbar {}
https://developer.mozilla.org/en/Writing_Efficient_CSS
writing efficient CSS5. avoid descendant selectors
• bad: UL LI A {}• better: UL > LI > A {}
6. avoid tag-child selectors• bad: UL > LI > A {}• best: .li-anchor {}
7. be wary of child selectors8. rely on inheritance
http://www.w3.org/TR/CSS21/propidx.html
https://developer.mozilla.org/en/Writing_Efficient_CSSby David Hyatt4/21/2000
testing massive CSS20K DIV > P > A elementsno style: controltag:
A {}class:
.a00001 {}
.a20000 {}descender:
DIV DIV DIV P A.a00001 {}child:
DIV > DIV > DIV > P > A.a00001 {}
http://jon.sykes.me/153/more-css-performance-testing-pt-33 revisions
CSS performance isn't linear
IE 7 "cliff" at 18K rules
real world levels of CSS
# Rules
# elements
Avg Depth
AOL 2289 1628 13eBay 305 588 14Facebook 2882 1966 17Google Search 92 552 8Live Search 376 449 12MSN.com 1038 886 11MySpace 932 444 9Wikipedia 795 1333 10Yahoo! 800 564 13YouTube 821 817 9
average 1033 923 12
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 pages30 ms avg delta
http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/
testing expensive selectors
1K rules (vs. 20K)same amount of CSS in
all test pages2126 ms avg delta!
truly expensive selectorA.class0007 * { ... }
compare to:DIV DIV DIV P A.class0007 { ... }
the key is the key selector – the rightmost argument
selectors to avoidA.class0007 DIV { ... }#id0007 > A { ... }.class0007 [href] { ... }DIV:first-child { ... }
http://stevesouders.com/efws/css-selectors/csscreate.php?sel=DIV%3Afirst-child
reflow time vs. load timereflow – time to apply CSS, re-layout elements,
and repainttriggered 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
reflow time by browser
reflow performance varies by browser and action"1x" ranges from 1-6 seconds depending on browser
DHTML action Chr1 Chr2 FF2 FF3IE6,7 IE 8 Op Saf3 Saf4
className 1x 1x 1x 1x 1x 1x 1x 1x 1xdisplay 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 1x 2x 1x 1x - 1x -background - - 1x 1x 1x - - - -font-size 1x 1x 1x 2x 1x 1x - 1x 1x
Simplifying CSS Selectors
efficient CSS comes at a cost – page weightfocus optimization on selectors where the key
selector matches many elementsreduce the number of selectors
questionsWhat's the surprise in how selectors are applied?What's the part of the selector is the key to focus
on for performance?Why do some of the selector optimizations
increase page weight?Why is reflow time important today?
morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance
morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance
state of performance2008
year of the browser2009
visibility into the browserweb devs think "Web 2.0"speed as a featureperformance standardsJavaScript helpperformance off the desktopfast-by-default
visibility into the browserhard to measure the exact things we're trying to optimize
• HTML parsing• CSS parsing• JS parsing and execution (as the page loads)• DOM manipulation
web page profiler (concept)paint events
memory
CPU
JavaScript CSS
web devs think "Web 2.0"the days of Web 1.0 are fading away...but web developers still think in terms of the page
reloading on every user actionWeb 2.0 pages may persist for hoursneed to evolve the way we program to keep our eyes
on the long run, for example:• vigilant about memory leaks• # of DOM elements• optimize JS and CSS for ongoing DHTML
speed as a featuresites use speed as a competitive advantage
• remember Yahoo! and Google search?• Facebook vulnerability?
aggregators & vendors prioritize based on speed• Google incorporates load time into Adwords Quality
Score• http://adwords.blogspot.com/2008/03/landing-page-load-
time-will-soon-be.html
performance standardstest suites for web sitesbenchmarks for browsersstandards for "response time"web page digest
archive of all relevant information about a page load
shared instrumentation and reporting
JavaScript helptools to automatically split (huge) Web 2.0
JavaScript payload into smaller initial module and larger later module(s)
a la Dolotohttp://research.microsoft.com/research/pubs/view.aspx?tr_id=1402
ability to specify Opera-like defer using HTML<script defer src=...><script afteronload src=...>
focus on other platformsproliferation of web clients besides desktop browsers...requires investigation and evangelism of performance
best practices for these platforms• mobile, PDA• auto, mass transit• airplane• 3rd world
fast by defaultI enjoy hard work......but we shouldn't have to spend this much time
solving the same problem again and againRuntime Page Optimizer
http://www.getrpo.com/Strangeloop
http://www.strangeloopnetworks.com/combine these with smush.it
takeawaysfocus on the frontendrun YSlow: http://developer.yahoo.com/yslow
this year's focus: JavaScriptspeed matters
impact on revenue
Google:Yahoo:
Amazon:
1 http://home.blarg.net/~glinden/StanfordDataMining.2006-11-29.ppt2 http://www.slideshare.net/stoyan/yslow-20-presentation
+500 ms -20% traffic1
+400 ms -5-9% full-page traffic2
+100 ms -1% sales1
cost savings
hardware – reduced loadbandwidth – 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 [email protected]
http://stevesouders.com/docs/oreilly-master-class-part2.ppt