260

today's class

  • Upload
    willis

  • View
    61

  • Download
    1

Embed Size (px)

DESCRIPTION

today's class. morning: how we got here HTTP overview High Performance Web Sites: Rules 1-6 break exercise: Web 100 stats High Performance Web Sites: Rules 7-14 afternoon: morning wrap-up Even Faster Web Sites: chapters 1-4 break Even Faster Web Sites: chapters 5-8 - PowerPoint PPT Presentation

Citation preview

Page 1: today's class
Page 2: 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

Page 3: today's class

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

Page 4: today's class

how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14

Page 5: today's class

17%

83%

iGoogle, primed cache

the importance of frontend performance

9% 91%

iGoogle, empty cache

Page 6: today's class

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%

Page 7: today's class

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

Page 8: today's class
Page 9: today's class

evangelismConferences

Web 2.0 ExpoThe Ajax ExperienceOSCONGoogle/IOSXSW

CompaniesYahoo!AmazonZillowMicrosoft

ConferencesWordCampFuture of Web AppsWidget SummitVelocityRich Web Experience

AppleNetflixTwitterLinkedIn

GoogleFacebookCBS Interactive

Page 10: today's class
Page 11: today's class
Page 12: today's class

September 2007

Page 13: today's class
Page 14: today's class

how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14

Page 15: today's class

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

Page 16: today's class

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...

Page 17: today's class

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...

Page 18: today's class

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:

Page 19: today's class

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?

Page 20: today's class

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

Page 21: today's class

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.

Page 22: today's class

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.

Page 23: today's class
Page 24: today's class

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)

Page 25: today's class
Page 26: today's class

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/

Page 27: today's class

YSlow

Page 28: today's class

YSlowSteve Souders, July 2007web performance analysis tooladd-on to Firebug (extension to an extension)Open Source (free), not open repositoryhttp://developer.yahoo.com/yslow/

Page 29: today's class

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?

Page 30: today's class

how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14

Page 31: today's class

17%

83%

iGoogle, primed cache

the importance of frontend performance

9% 91%

iGoogle, empty cache

Page 32: today's class

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.

Page 33: today's class

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%

Page 34: today's class

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

Page 35: today's class

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/

Page 36: today's class

Rule 1: Make Fewer HTTP Requests

But...is it possible to reduce HTTP requests without

reducing richness?Yes:

combine JS, CSSimage mapsCSS spritesinline images

Page 37: today's class

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

Page 38: today's class

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

Page 39: today's class

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

Page 40: today's class

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

Page 41: today's class

data: URLsnot just for imagesHammerhead:<frame src="data:text/html,%3Chtml%3E%3Cbody%20style%3D%22background..."></frame>

Page 42: today's class

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

Page 43: today's class

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

Page 44: today's class

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

Page 45: today's class

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?

Page 46: today's class

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...

Page 47: today's class

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

Page 48: today's class

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

Page 49: today's class

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

Page 50: today's class

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

Page 51: today's class

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

Page 52: today's class

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?

Page 53: today's class

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...

Page 54: today's class

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%

Page 55: today's class

pros and consPro:

smaller transfer sizeCon:

CPU cycles – on client and server

Don't compress resources < 1K

Page 56: today's class

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

Page 57: today's class

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

Page 58: today's class

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

Page 59: today's class

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

Page 60: today's class

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

Page 61: today's class

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

Page 62: today's class

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

Page 63: today's class

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

Page 64: today's class

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

Page 65: today's class

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

Page 66: today's class

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?

Page 67: today's class

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

Page 68: today's class

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

Page 69: today's class

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

Page 70: today's class

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

Page 71: today's class

FF2: stylesheets block

stylesheets block downloads in Firefox 2

fixed in Firefox 3

Page 72: today's class

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

Page 73: today's class

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

Page 74: today's class

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?

Page 75: today's class

parallelization is an opportunity for improving load times

Page 76: today's class

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

Page 77: today's class

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

Page 78: today's class

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

Page 79: today's class

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?

Page 80: today's class

how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14

Page 81: today's class

how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14

Page 82: today's class

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

Page 83: today's class

how we got hereHTTP overviewHPWS Rules 1-6breakweb 100HPWS 7-14

Page 84: today's class

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

Page 85: today's class

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

Page 86: today's class

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

Page 87: today's class

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>

Page 88: today's class

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

Page 89: today's class

questionsHow do CSS expressions affect performance?What are two workarounds to this problem with

CSS expressions?

Page 90: today's class

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

Page 91: today's class

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

Page 92: today's class

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

Page 93: today's class

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'>

Page 94: today's class

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

Page 95: today's class

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

Page 96: today's class

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

Page 97: today's class

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

Page 98: today's class

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

Page 99: today's class

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?

Page 100: today's class

Rule 9: Reduce DNS Lookupstypically take 20-100ms, sometimes > 500msOS and browsers cache DNS resolutions

Page 101: today's class

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

Page 102: today's class

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

Page 103: today's class

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

Page 104: today's class

Reducing DNS Lookupsuse Keep-Aliveadding DNS lookups vs. domain shardingidentify dominant domain names, reduce non-

dominant namesfor dominant domains – shard across 2-4

CNAMEs

Page 105: today's class

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?

Page 106: today's class

Rule 10: Minify JavaScriptminification: removing unnecessary characters

from code (comments, white space, etc.)obfuscation: minify as well as reduce length of

symbol names (munge)

Page 107: today's class

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/

Page 108: today's class

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

Page 109: today's class

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/

Page 110: today's class

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

Page 111: today's class

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

Page 112: today's class

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

Page 113: today's class

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

Page 114: today's class

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

Page 115: today's class

questionsWhat's the difference between minification and

obfuscation?How do they compare wrt reducing JavaScript size?What are three drawbacks to obfuscation?

Page 116: today's class

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

Page 117: today's class

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

Page 118: today's class

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

Page 119: today's class

"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

Page 120: today's class

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

Page 121: today's class

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

Page 122: today's class

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

Page 123: today's class

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

Page 124: today's class

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

Page 125: today's class

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

Page 126: today's class

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?

Page 127: today's class

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

Page 128: today's class

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

Page 129: today's class

questionsWhat are two typical causes of duplicate scripts?

In what way(s) can duplicate scripts be bad for performance?

Page 130: today's class

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

Page 131: today's class

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

Page 132: today's class

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...

Page 133: today's class

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

Page 134: today's class

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

Page 135: today's class

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

Page 136: today's class

INM, IMS hit & miss

hit miss

hit 304 full response

miss

If-Modified- Since

If-None-Match

Page 137: today's class

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.

Page 138: today's class

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

Page 139: today's class

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"

Page 140: today's class

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"

Page 141: today's class

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

Page 142: today's class

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"

Page 143: today's class

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/

Page 144: today's class

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 –

Page 145: today's class

possible uses for ETags???

Page 146: today's class

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?

Page 147: today's class

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

Page 148: today's class

Ajax optimizationsadd an Expires headergzip componentsminify JavaScriptavoid redirectsconfigure ETags

most important

Page 149: today's class

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?

Page 150: today's class

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

Page 151: today's class

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

Page 152: today's class

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?

Page 153: today's class

LUNCH!

Page 154: today's class

morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance

Page 155: today's class

morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance

Page 156: today's class

September 2007

Page 157: today's class

June 2009

Page 158: today's class

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

Page 159: today's class

AOLeBayFacebookMySpaceWikipediaYahoo!

why focus on JavaScript?

YouTube

Page 160: today's class

scripts block

<script src="A.js"> blocks parallel downloads and rendering

http://stevesouders.com/cuzillion/?ex=10008

Page 161: today's class

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

Page 162: today's class

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

Page 163: today's class

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

Page 164: today's class

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?

Page 165: today's class

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?

Page 166: today's class

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

Page 167: today's class

Loading Scripts Without Blocking

XHR Eval

XHR Injection

Script in Iframe

Script DOM Element

Script Defer

document.write Script Tag

Page 168: today's class

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

Page 169: today's class

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

Page 170: today's class

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

Page 171: today's class

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

Page 172: today's class

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

Page 173: today's class

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

Page 174: today's class

browser busy indicators

Page 175: today's class

browser busy indicators

good to show busy indicators when the user needs feedbackbad when downloading in the background

Page 176: today's class

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

Page 177: today's class

asynchronous loading traits

*Only other document.write scripts are downloaded in parallel (in the same script block).

Page 178: today's class

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

Page 179: today's class

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"

Page 180: today's class

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/

Page 181: today's class

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?

Page 182: today's class

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?

Page 183: today's class
Page 184: today's class

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>

Page 185: today's class

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

Page 186: today's class

before

after

Page 187: today's class

asynchronous loading traits

*Only other document.write scripts are downloaded in parallel (in the same script block).

!IE

Page 188: today's class

what about

inlined code that depends on the script?

Page 189: today's class

Coupling Asynchronous Scripts

hardcoded callbackwindow onloadtimerdegrading script tagsscript onload

Page 190: today's class

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

Page 191: today's class

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

Page 192: today's class

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

Page 193: today's class

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

Page 194: today's class

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...)

Page 195: today's class

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

Page 196: today's class

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

Page 197: today's class

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

Page 198: today's class

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

Page 199: today's class

questionsHow can you load an external script

asynchronously, and have an inline script execute as soon as the external script is loaded?

Page 200: today's class

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

Page 201: today's class

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?

Page 202: today's class

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

Page 203: today's class

eBayMSNMySpaceWikipedia

examples of scattered scripts

Page 204: today's class

Positioning Inline Scripts

remember inline scripts carry a costavoid long-executing inline scriptsdon't put inline scripts between stylesheets and

other resources

Page 205: today's class

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?

Page 206: today's class

morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance

Page 207: today's class

morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance

Page 208: today's class

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

Page 209: today's class

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

Page 210: today's class

www.yahoo.com

Page 211: today's class

http://news.google.com

news.google.com

Page 212: today's class

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/

Page 213: today's class

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

Page 214: today's class

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

Page 215: today's class

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?

Page 216: today's class

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()

Page 217: today's class

where to flush

after a few resourcesafter some content the user will seebefore the backend part that is slow

Page 218: today's class

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)

Page 219: today's class

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

Page 220: today's class

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?

Page 221: today's class

Using Iframes Sparingly

load 100 empty elements of each type

iframes are 10-100x more expensive

Page 222: today's class

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>

Page 223: today's class

scripts block iframe

no surprise – scripts in the parent block the iframe from loading

IE

Firefox

Safari Chrome

Opera

script

script

script

Page 224: today's class

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

Page 225: today's class

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

Page 226: today's class

iframes: no free connections

iframe shares connection pool with parent (here – 2 connections per server in IE 7)

iframe

parent

Page 227: today's class

questionsWhy are iframes the most expensive DOM

element?Why is the fact that iframes block the onload

event bad?

Page 228: today's class

Simplifying CSS Selectors

#toc > LI { font-weight: bold; }

combinatorsimple selectors

selector

declaration block

rule

http://stevesouders.com/efws/selectors.php

Page 229: today's class

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

Page 230: today's class

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

Page 231: today's class

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

Page 232: today's class

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

Page 233: today's class

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

Page 234: today's class

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

Page 235: today's class

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

Page 236: today's class

CSS performance isn't linear

IE 7 "cliff" at 18K rules

Page 237: today's class

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

Page 238: today's class

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/

Page 239: today's class

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

Page 240: today's class

selectors to avoidA.class0007 DIV { ... }#id0007 > A { ... }.class0007 [href] { ... }DIV:first-child { ... }

http://stevesouders.com/efws/css-selectors/csscreate.php?sel=DIV%3Afirst-child

Page 241: today's class

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

Page 242: today's class

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

Page 243: today's class

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

Page 244: today's class

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?

Page 245: today's class

morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance

Page 246: today's class

morning wrap-upEFWS 1-4breakEFWS 5-8performance analysisstate of performance

Page 247: today's class

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

Page 248: today's class

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

Page 249: today's class

web page profiler (concept)paint events

memory

CPU

JavaScript CSS

Page 250: today's class

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

Page 251: today's class

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

Page 252: today's class

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

Page 253: today's class

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=...>

Page 254: today's class

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

Page 255: today's class

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

Page 256: today's class

takeawaysfocus on the frontendrun YSlow: http://developer.yahoo.com/yslow

this year's focus: JavaScriptspeed matters

Page 257: today's class

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

Page 258: today's class

cost savings

hardware – reduced loadbandwidth – reduced response size

http://billwscott.com/share/presentations/2008/stanford/HPWP-RealWorld.pdf

Page 259: today's class

if you want better user experience more revenue reduced operating expenses

the strategy is clear

Even Faster Web Sites

Page 260: today's class

Steve [email protected]

http://stevesouders.com/docs/oreilly-master-class-part2.ppt