We here at Load Impact are always interested in learning more about browser behaviour, and when we saw Steve Souders new Browserscope project, we really liked it and decided to help out, if we could. Browserscope profiles web browsers, and tries to determine what browsers have support for new features, are suffering from known security issues, or have certain performance-affecting "quirks". It basically runs an extensive test suite on your browser and tells you how good your browser is. Go and check it out, we think it is very cool.
Naturally, we are most interested in the performance-affecting "quirks" browsers have. These mostly fall under the "Network" category in Browserscope (go to browsercope.org and click on the Network tab) and can be stuff like how many concurrent TCP connections a certain browser will open to one and the same host. Internet Explorer 7 will only open max 2 concurrent connections to a webserver, while Internet Explorer 8 will open up to 6 concurrent connections. That means that IE8 can download 6 files at the same time, while IE7 can only download 2 files at the same time. It definitely affects performance, and as such, is very interesting to us (note that the opening of many connections might be a good thing from a client perspective, but worse for the server that has to keep a ton of connections open - we don't advocate opening more connections as a universal way to increase performance...)
We have actually modeled our Web page analyzer on these performance-affecting characteristics that Browserscope has identified for us. Our web page analyzer can emulate different well-known browsers when it analyzes a web page, and the way it does that is by mimicking the behaviours you can read about under the Browserscope Network test category. It emulates browser-specific performance-affecting behavour such as the max number of concurrent TCP connections to open, etc. and thanks to this it can provide fairly accurate predictions of page load times in most major browsers.
Anyway, we decided to try and create a Browserscope test to see what browsers support HTTP trailing headers. This is a feature of HTTP 1.1 that very few browsers have implemented. It means that a server can transmit extra HTTP headers after the HTTP body has been sent. It is useful if, for example, a server generates a large PDF file dynamically and wants to include a checksum (using the Content-MD5 HTTP header), but wants to start sending the file immediately and avoid buffering the whole of the file in RAM. If the browser at the other end support HTTP trailing headers, the server can generate the file while sending it, and while computing the checksum on the fly. Then when the file has been transmitted, the server just add the Content-MD5 HTTP header at the end.
The new test is live at browserscope.org now. It lies under the Network category and is called "Headers in trailers". As you can see, it is only Opera (and Palm Pre!) that seem to support the feature
And now for something really strange
That was a case of finding out whether browsers support a standard HTTP feature or not, but there was also another, more exotic browser characteristic we wanted to dig into. The strange phenomenon that most modern browsers always send Ajax HTTP POST requests as two or more TCP packets. That is, even if the request is small enough to fit into a single packet.
This was apparently first observed by a Yahoo developer, then re-posted a couple of times until Joseph Scott tested various browsers to see which were affected, and found out that most browsers had this tendency, with Firefox being a notable exception. Many have speculated about the possible performance impact of this, and Yahoo have actually incorporated it into their Best Practises for Speeding Up Your Web Site as a separate rule/tip, where they advise people to use GET instead of POST requests in javascript code, because the POST requests may be transmitted using an extra TCP packet. But there is precious little hard data about what this browser behaviour actually does for performance, and we also thought the browser survey done by Joseph Scott was a bit incomplete, so we set out to investigate a bit more.
First, we performed a major survey where we learned that Sea Monkey, Galeon and most versions of Firefox (on various platforms), were the only browsers that sent short HTTP POST requests as a single TCP packet. The rest of the bunch always sent one TCP packet containing just HTTP headers, and one or more TCP packets containing the HTTP body, when a javascript performed an HTTP POST request (note that this only applies to javascript-generated requests).
Then we wanted to find out how big the performance impact was. We imagined that an Ajax application performing a lot of small HTTP POST requests over a high-latency, high-packetloss link would see its performance deteriorate badly due to the extra time spent resending lost packets, if the user used one of the browsers always sending two packets instead of one. More packets equal more packets lost, which means more waiting for resend timeouts and then more resending of packets.
So, we set up a test bed where we simulated packet loss and network delay between client and server. Then we let the 1-packet browser Firefox compete against the 2-packet browser Safari, to see which one fared the worst. The results were a bit surprising. It turned out that while both browsers saw their average transaction times deteriorate substantially with increased network delay and increased packet loss, Safari did slightly better than Firefox overall. The increase in average transaction time due to packet loss in Safari were not as great as the same increase in Firefox. If you're having a slow day and want more detail, here is a PDF report from the tests.
And you people who aren't very interested in arcane TCP matters can probably stop reading now :-)
Why is sending two packets just as good as, or better than, sending one? I have been discussing this with some networking people on an email list recently, and two possible answers came up:
- if packet #1 sent by Safari is lost, retransmission will occur faster if packet #2 gets delivered, as the receiver will ACK packet #2, whereupon the sender will see that receiver is still waiting for packet #1 and most likely also lower its retransmission timeout for packet #1.
- sending more packets allows TCP to keep better track of network roundtrip times, which are used to set reasonable retransmission timeout values.
What is really interesting here is that the results seem to go against the Yahoo recommendations. There seems to be no discernible performance hit for using POST requests. At least not on the client side. We would love to hear from people who are more familiar with current TCP implementations and who can offer some explanations for this behaviour.
