Optimizing Page Load Times
John Callender writes, "Google engineer Aaron Hopkins has written an interesting analysis of optimizing page load time. Hopkins simulated connections to a web page consisting of many small objects (HTML file, images, external javascript and CSS files, etc.), and looked at how things like browser settings and request size affect perceived performance. Among his findings: For web pages consisting of many small objects, performance often bottlenecks on upload speed, rather than download speed. Also, by spreading static content across four different hostnames, site operators can achieve dramatic improvements in perceived performance."
If the user were to enable pipelining in his browser (such as setting Firefox's network.http.pipelining in about:config), the number of hostnames we use wouldn't matter, and he'd make even more effective use of his available bandwidth. But we can't control that server-side.
i ning-faq.html
For those that don't know what that means: http://www.mozilla.org/projects/netlib/http/pipel
I've had it switched on for ages. I sometimes wonder why it's off by default.
http://twitter.com/onion2k
From TFA:
And:
From RFC 2616, section 8.1.4:
It's not a browser quirk, it's specified behavior.
If you are on a fast broadband pipe you are correct but there is still a lot of other people on small connections with low upload limits (64k-256kbit) and I can see why this could be a bottle neck as it can't get the requests out fast enough. That said there are things a user can do to help themselves.
Firstly if the ISP has a proxy server then using it will reduce the trip time for some stored content meaning it only has to go over a few hops than prehaps all the way across the world. You can also look at something like Onspeed which is a paid for product but compresses images (though makes them look worse) and content and can give a decent boost on very slow (GPRS/3G) connections and also get more out of your transfer quota.
Cheap UK and US VPS
"Regularly use your site from a realistic net connection. Convincing the web developers on my project to use a "slow proxy" that simulates bad DSL in New Zealand (768Kbit down, 128Kbit up, 250ms RTT, 1% packet loss) rather than the gig ethernet a few milliseconds from the servers in the U.S. was a huge win. We found and fixed a number of usability and functional problems very quickly."
What (free) simulation is available for this? I only know dummynet which requires a linux server and some advanced routing. But surely there is more. Is there?
1.5Mbps ADSL.
5 Seconds to refresh the page on slashdot. That's just to getting the page to actually blank and refresh, there's still then the time it takes to load all the comments.
Sometimes it's near instant, but most of the time it's around about that.
Most of the time is spent "Waiting for slashdot.org", or "connecting to images.slashdot.org".
It used to be a hell of a lot worse, but I installed adblock to eliminate all the extra unecesary connections (google analytics, and the various ad servers). I didn't care about the ads or the tracking, it just bugged me that those things made my browsing experience slower.
I find it funny that this guy is suggesting spreading across multiple hosts, it's my completely unscientific and entirely anecdotal experience that the more host names the browser has to resolve to load the page, the longer it takes before you get to see anything.
I'm in Australia so there's a minimum 200 ms latency on roundtrips - five roundtrips and you've added 1 second to the rendering time. Approaches that add extra DNS lookups really aren't going to help. (Though the DNS lookups themselves aren't necesarily going to take 200ms - they could be much faster if they're in my ISPs DNS cache, or the could be longer if it's got to query them)
Advanced users are users too!
I've done some benchmarks and measurements in the past which will never be made public (I work for Yahoo!). And the most important bits in those have been CSS and Scripts. A lot of performance has been squeezed out of the HTTP layers (akamai, Expires headers), but not enough attention has been paid to the render section of the experience. You could possibly reproduce the benchmarks with a php script which does a sleep() for a few seconds to introduce delays at various points and with a weekend to waste.
The page does not start rendering till the last CSS stream is completed, which means if your css has @import url() entries, the delay before render increases (until that file is pulled & parsed too). It really pays to have the quickest load for the css data over anything else - because without it, all you'll get it a blank page for a while.
Scripts marked defer do not always defer and a lot of inline code in <script> tags depend on such scripts that a lot of browsers just pull the scripts as and when they find it. There seems to be just two threads downloading data in parallel (from one hostname), which means a couple of large (but rarely used) scripts in the code will block the rest of the css/image fetches. See flickr's organizr for an example of that in action.
You should understand that these resources have different priorities in the render land and you should really only venture here after you've optimized the other bits (server and application).
All said and done, good tutorial by Aaron Hopkins - a lot of us have had to rediscover all that (& more) by ourselves.
Quidquid latine dictum sit, altum videtur
This is a good place to start testing the 'cacheability' of your dynamic web pages. Quite frankly it's appauling that even the big common web apps used today like most forum or blog scripts don't generate sensible Last-Modified, Vary, Expires, Cache-Control headers. With most of the metadata you need to generate this stuff stored in the existing database scheme theres just really no excuse for it.
Abolishment of nasty long query strings into nicer, more memorable URI's is also something we should be seeing more of in "Web 2.0." Use mod_rewrite, you'll feel better for it.
If a big part of your job involves using a Web-based application, reducing page-load times really helps. My real job is writing one of these applications and getting the caching right is much more important than sexier topics like AJAX. There's some good advice in TFA.
Reduce, reuse, cycle
``By default, IE allows only two outstanding connections per hostname when talking to HTTP/1.1 servers or eight-ish outstanding connections total. Firefox has similar limits.''
...) in it (i.e., most web pages), and lots of these objects are going to be requested sequentially, costing you lots of round trip times.
Anybody know why? This seems pretty dumb to me. Request a page with several linked objects (images, stylesheets, scripts,
Please correct me if I got my facts wrong.
FTFA:
``Most DSL or cable Internet connections have asymmetric bandwidth, at rates like 1.5Mbit down/128Kbit up, 6Mbit down/512Kbit up, etc. Ratios of download to upload bandwidth are commonly in the 5:1 to 20:1 range. This means that for your users, a request takes the same amount of time to send as it takes to receive an object of 5 to 20 times the request size. Requests are commonly around 500 bytes, so this should significantly impact objects that are smaller than maybe 2.5k to 10k. This means that serving small objects might mean the page load is bottlenecked on the users' upload bandwidth, as strange as that may sound.''
I've said for years that HTTP requests are larger than they should be. It's good to hear it confirmed by someone who's taken seriously. This is even more of an issue when doing things like AJAX, where you send HTTP requests and receive HTTP responses + XML verbosity for what should be small and quick user interface actions.
Please correct me if I got my facts wrong.
Pipelining is not the same as keep-alive. Although pipelining needs a keep-alive connection.
Pipeling means "multiple requests can be sent before any responses are received. "
There are other factors.
1 - keepalive/pipelining connections means only 1 dns lookup is performed, often cached on your local machine means this delay is minimal.
2 - the dns lookup can be happening for the second host while connections to the first host are still downloading, rather than stopping everything while the second host is looked up. This hides the latency of the second lookup.
3 - most browsers limit the number of connections to each server to 2. If you're loading loads of images, this means you can only be loading two at once (or one while the rest of the page is still downloading). If you put images on a different host, you can get extra connections to it. Also, cookies will usually stop an object from taking advantage of proxies/caches. Putting images on a different host is an easy to way make sure they're not cookied.
The revolution will not be televised... but it will have a page on Wikipedia
Pipelining is not keep-alive. Keep alive means sending multiple requests down one connection, waiting for the response to the request before sending the next. Pipelining sends all the requests at once without waiting.
Keep-alive no:
Open connection
-Request
-Response
Close Connection
Open connection
-Request
-Response
Close Connection
-Repeat-
Keep-alive yes:
Open connection
-Request
-Response
-Request
-Response
-Repeat-
Close Connection
Pipe-lining yes:
Open connection
-Request
-Request
-Repeat-
-Response
-Response
-Repeat-
Close Connection
I hope they apply this study on Gmail. Using it on a non-broadband connection (plain 56k modem) is a pain unless you use the pure HTML view that is crap compared to other HTML webmails.
The fun is that newer AJAX products from google (like goffice) don't suffer from this behavior, they have a much more cleaner code (just pick view code on your favorite browser and see). Probally Gmail HTML/Javascript is already showing it's age, and paying the price for being a first at google AJAX apps.
Keep-alive sends the next request after the first has completed, but on the same connection (this requires the server to send Content-length: header, so it knows after how many bytes the page has finished loading. Without this, the server must close the connection so the browser knows it's done).
Pipelining sends requests out without having to wait for the previous to complete (this does also require a Content-length: header. This is fine for static files, such as images, but many scripts where output is sent straight to the browser as it's being generated will break this, as it won't know the content length until generated has completed).
The revolution will not be televised... but it will have a page on Wikipedia
I've had it switched on for ages. I sometimes wonder why it's off by default.
Some reasons against pipelining.
User perception of responsiveness on interfaces has a lower bound of 200 ms. Some times even lower.
Just because 1 seconds seems fast, it doesn't mean that it's fast enough to stop improving.
When you reach that 200ms barrier, the interface has perfect responsiveness, a bigger interval is always perfectible.
You mean creating four hostnames for the same address? Or do you mean changing a few src="" attributes?
Wrong. It leaves us with nothing. Didn't you read the article? HTTP Pipelining isn't enabled in the big two web browsers, so as far as "reality" is concerned it doesn't exist. It's like IPV6- who cares how much "better" it is if no one is using it?
Has anyone played around with multipart/mixed or such replies? These could reduce the number of requests but is there any support for them in browsers?
This is an excellent argument for ad blocking. The article never mentions the basic truth - almost all offsite content on web pages is ads. (Of course, this is someone from Google talking, and Google, after all, is an ad-delivery service which runs a search engine to boost their hits.) Web page load is choking on ads. I noted previously that some sites load ads from as many as six different sources. This saturates the number of connections the browser supports. Page load then bottlenecks on the slowest ad server.
So install AdBlock and FlashBlock in Firefox, and watch your browsing speed up.
Web-based advertising looks like a saturated market. Watch for some big bankruptcies among advertising-supported services.