How to improve web server performance – Based on the 14 Steve Sounders’s Rules
Today mostly of web sites the Web 2.0 Technology which combining the AJAX technology, RSS, Video steaming, and also containing many more rich images and flash.
The performance of the site will be decreased significantly if the sites is a popular site. The rules are getting from the Steve Sounders Presentation on Yahoo UI Blog and his book High Performance Web Sites – Essential knowledge for Front-End Engineers.
The rules as below :
- Make fewer HTTP requests
- Use a CDN
- Add an Expires header
- Gzip components
- Put CSS at the top
- Move JS to the bottom
- Avoid CSS expressions
- Make JS and CSS external
- Reduce DNS lookups
- Minify JS
- Avoid redirects
- Remove duplicate scripts
- Turn off ETags
- Make AJAX cacheable and small
Rule 1: Make fewer HTTP requests
- Image maps
- CSS sprites
- Inline images
- Combined scripts, combined stylesheets
Image maps
server-side
<a href=”navbar.cgi”><img ismap src=”imagemap.gif”></a>
→ http://…/navbar.cgi?127,13
client-side – preferred
<img usemap=”#map1″ border=0 src=”/images/imagemap.gif”>
<map name=”map1″>
<area shape=”rect” coords=”0,0,31,31″ href=”home.html” title=”Home”>
…
</map>
Drawbacks:
– must be contiguous
– defining area coordinates – tedious, errors
CSS Sprites – Preferred
<span style=”
background-image: url(’sprites.gif’);
background-position: -260px -90px;”>
</span>
size of combined image is less
not supported in Opera 6
http://alistapart.com/articles/sprites
Inline Images
- data: URL scheme
- not supported in IE
- avoid increasing size of HTML pages:
- put inline images in cached stylesheets
Combined Scripts, Combined Stylesheets
|
|
Scripts |
Stylesheets |
|
amazon.com |
3 |
1 |
|
aol.com |
18 |
1 |
|
cnn.com |
11 |
2 |
|
ebay.com |
7 |
2 |
|
froogle.google.com |
1 |
1 |
|
msn.com |
9 |
1 |
|
myspace.com |
2 |
2 |
|
wikipedia.org |
3 |
1 |
|
yahoo.com |
4 |
1 |
|
youtube.com |
7 |
3 |
|
Average |
6.5 |
1.5 |
combining six scripts into one eliminates five HTTP requests
challenges:
– develop as separate modules
– number of possible combinations vs. loading more than needed
– maximize browser cache
one solution:
– dynamically combine and cache
Rule 2: Use a CDN
|
amazon.com |
Akamai |
|
aol.com |
Akamai |
|
cnn.com |
|
|
ebay.com |
Akamai, Mirror Image |
|
google.com |
|
|
msn.com |
SAVVIS |
|
myspace.com |
Akamai, Limelight |
|
wikipedia.org |
|
|
yahoo.com |
Akamai |
|
youtube.com |
|
distribute your static content before distributing your dynamic content
Rule 3: Add an Expires header
not just for images
|
|
Images |
Stylesheets |
Scripts |
% |
Median Age |
|
amazon.com |
0/62 |
0/1 |
0/3 |
0% |
114 days |
|
aol.com |
23/43 |
1/1 |
6/18 |
48% |
217 days |
|
cnn.com |
0/138 |
0/2 |
2/11 |
1% |
227 days |
|
ebay.com |
16/20 |
0/2 |
0/7 |
55% |
140 days |
|
froogle.google.com |
1/23 |
0/1 |
0/1 |
4% |
454 days |
|
msn.com |
32/35 |
1/1 |
3/9 |
80% |
34 days |
|
myspace.com |
0/18 |
0/2 |
0/2 |
0% |
1 day |
|
wikipedia.org |
6/8 |
1/1 |
2/3 |
75% |
1 day |
|
yahoo.com |
23/23 |
1/1 |
4/4 |
100% |
n/a |
|
youtube.com |
0/32 |
0/3 |
0/7 |
0% |
26 days |
Rule 4: Gzip components
You can affect users’ download times 90%+ of browsers support compression
Gzip vs. Deflate
|
|
|
Gzip |
Deflate |
||
|
|
Size |
Size |
Savings |
Size |
Savings |
|
Script |
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% |
Gzip compresses more
Gzip supported in more browsers
Gzip: not just for HTML
|
|
HTML |
Scripts |
Stylesheets |
|
amazon.com |
x |
|
|
|
aol.com |
x |
some |
some |
|
cnn.com |
|
|
|
|
ebay.com |
x |
|
|
|
froogle.google.com |
x |
x |
x |
|
msn.com |
x |
deflate |
deflate |
|
myspace.com |
x |
x |
x |
|
wikipedia.org |
x |
x |
x |
|
yahoo.com |
x |
x |
x |
|
youtube.com |
x |
some |
some |
gzip scripts, stylesheets, XML, JSON (not images, PDF)
Gzip Configuration
Apache 2.x: mod_deflate
AddOutputFilterByType DEFLATE text/html text/css application/x-javascript
HTTP request
Accept-Encoding: gzip, deflate
HTTP response
Content-Encoding: gzip
Vary: Accept-Encoding
Gzip Edge Cases
<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
Consider adding Cache-Control: Private
Remove ETags (Rule 13)
Rule 5: Put CSS at the top
stylesheets block rendering in IE
http://stevesouders.com/examples/css-bottom.php
solution: put stylesheets in HEAD (per spec)
avoids Flash of Unstyled Content
use LINK (not @import)
Slowest is Fastest
Rule 6: Move scripts to the bottom
Scripts block parallel downloads across all hostnames. Scripts block rendering of everything below them in the page
IE and FF
http://stevesouders.com/examples/js-middle.php
script defer attribute is not a solution
– blocks rendering and downloads in FF
– slight blocking in IE
solution: move them as low in the page as possible
Rule 7: Avoid CSS expressions
used to set CSS properties dynamically in IE
width: expression(
document.body.clientWidth < 600 ?
“600px” : “auto” );
problem: expressions execute many times
– mouse move, key press, resize, scroll, etc.
http://stevesouders.com/examples/expression-counter.php
One-Time Expressions
Expression overwrites itself
<style>
P {
background-color: expression(altBgcolor(this));
}
</style>
<script>
function altBgcolor(elem) {
elem.style.backgroundColor = (new Date()).getHours()%2 ? “#F08A00″ : “#B8D4FF”;
}
</script>
Event Handlers
Tie behavior to (fewer) specific events
window.onresize = setMinWidth;
function setMinWidth() {
var aElements =
document.getElementsByTagName(“p”);
for ( var i = 0; i < aElements.length; i++ ) {
aElements[i].runtimeStyle.width = (
document.body.clientWidth<600 ?
“600px” : “auto” );
}
}
Rule 8: Make JS and CSS external
Inline: HTML document is bigger
External: more HTTP requests, but cached
Variables
– page views per user (per session)
– empty vs. full cache stats
– component re-use
External is typically better
– home pages may be an exception
Post-Onload Download
Inline in front page
Download external files after onload
window.onload = downloadComponents;
function downloadComponents() {
var elem = document.createElement(“script”);
elem.src = “http://…/file1.js”;
document.body.appendChild(elem);
…
}
speeds up secondary pages
Dynamic Inlining
- start with post-onload download
- set cookie after components downloaded
server-side:
– if cookie, use external
– else, do inline with post-onload download
cookie expiration date is key
speeds up all pages
Rule 9: Reduce DNS lookups
Typically 20-120 ms
Block parallel downloads
OS and browser both have DNS caches
TTL (Time To Live)
|
www.amazon.com |
1 minute |
|
www.aol.com |
1 minute |
|
www.cnn.com |
10 minutes |
|
www.ebay.com |
1 hour |
|
www.google.com |
5 minutes |
|
www.msn.com |
5 minutes |
|
www.myspace.com |
1 hour |
|
www.wikipedia.org |
1 hour |
|
www.yahoo.com |
1 minute |
|
www.youtube.com |
5 minutes |
TTL – how long record can be cached browser settings override TTL
IE
- DnsCacheTimeout: 30 minutes
- KeepAliveTimeout: 1 minute
- ServerInfoTimeout: 2 minutes
Firefox
- network.dnsCacheExpiration: 1 minute
- network.dnsCacheEntries: 20
- network.http.keep-alive.timeout: 5 minutes
- Fasterfox: 1 hour, 512 entries, 30 seconds
Reducing DNS Lookups
- Fewer hostnames – 2-4
- Keep-alive
Rule 10: Minify JavaScript
|
|
Minify External? |
Minify Inline? |
|
www.amazon.com |
no |
no |
|
www.aol.com |
no |
no |
|
www.cnn.com |
no |
no |
|
www.ebay.com |
yes |
no |
|
froogle.google.com |
yes |
yes |
|
www.msn.com |
yes |
yes |
|
www.myspace.com |
no |
no |
|
www.wikipedia.org |
no |
no |
|
www.yahoo.com |
yes |
yes |
|
www.youtube.com |
no |
no |
Minify inline scripts, too
Minify vs. Obfuscate
|
|
Original |
JSMin Savings |
Dojo Savings |
|
www.amazon.com |
204K |
31K (15%) |
48K (24%) |
|
www.aol.com |
44K |
4K (10%) |
4K (10%) |
|
www.cnn.com |
98K |
19K (20%) |
24K (25%) |
|
www.myspace.com |
88K |
23K (27%) |
24K (28%) |
|
www.wikipedia.org |
42K |
14K (34%) |
16K (38%) |
|
www.youtube.com |
34K |
8K (22%) |
10K (29%) |
|
Average |
85K |
17K (21%) |
21K (25%) |
Minify – it’s safer
http://crockford.com/javascript/jsmin
http://dojotoolkit.org/docs/shrinksafe
Rule 11: Avoid redirects
- 3xx status codes – mostly 301 and 302
- HTTP/1.1 301 Moved Permanently
- Location: http://stevesouders.com/newuri
- add Expires headers to cache redirects
worst form of blocking
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
Redirects
|
|
Redirects |
|
www.amazon.com |
no |
|
www.aol.com |
yes – secondary page |
|
www.cnn.com |
yes – initial page |
|
www.ebay.com |
yes – secondary page |
|
froogle.google.com |
no |
|
www.msn.com |
yes – initial page |
|
www.myspace.com |
yes – secondary page |
|
www.wikipedia.org |
yes – secondary page |
|
www.yahoo.com |
yes – secondary page |
|
www.youtube.com |
no |
Avoid Redirects
Missing trailing slash
- http://astrology.yahoo.com/astrology
- use Alias or DirectorySlash
- mod_rewrite
- CNAMEs
- Log referer – track internal links
Outbound links – harder
- beacons – beware of race condition
- XHR – bail at readyState 2
Rule 12: Remove duplicate scripts
Hurts performance
- extra HTTP requests (IE only)
- extra executions
A typical?
- 2 of 10 top sites contain duplicate scripts
- team size, # of scripts
Script Insertion Functions
<?php
function 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>”;
}
?>
Rule 13: Turn off ETags
Unique identifier returned in response
- ETag: “c8897e-aee-4165acf0″
- Last-Modified: Thu, 07 Oct 2004 20:54:08 GMT
- used in conditional GET requests
- If-None-Match: “c8897e-aee-4165acf0″
- If-Modified-Since: Thu, 07 Oct 2004 20:54:08 GMT
- if ETag doesn’t match, can’t send 304
The Problem with ETags
ETag for a single entity is always different across servers
ETag format
- Apache: inode-size-timestamp
- IIS: Filetimestamp:ChangeNumber
Sites with >1 server return too few 304s
- (n-1)/n
Remove them
- Apache: FileETag none
- IIS: http://support.microsoft.com/kb/922703/
Rule 14: Make AJAX cacheable and small
XHR, JSON, iframe, dynamic scripts can still be cached, minified, and gzipped
a personalized response should still be cacheable by that person
AJAX Example: Yahoo! Mail Beta
address book XML request
→ GET /yab/[...]&r=0.5289571053069156 HTTP/1.1
Host: us.xxx.mail.yahoo.com
← HTTP/1.1 200 OK
Date: Thu, 12 Apr 2007 19:39:09 GMT
Cache-Control: private,max-age=0
Last-Modified: Sat, 31 Mar 2007 01:17:17 GMT
Content-Type: text/xml; charset=utf-8
Content-Encoding: gzip
address book changes infrequently
- cache it; add last-modified-time in URL




