Last weekend I was at Shmoocon, getting my annual fix of hacker-socialness. Unrelated to the conference I caught a tweet from @KatieHaxx:
— Katie (@KatieHaxx) January 17, 2015
And if you go to www.httpvshttps.com you may be as surprised as I was.
https was 70% faster than http.
If you’re not as shocked as I was you either already understand the technology I’m about to talk about or you don’t fall into counter-intuitive traps! Well here is why I was surprised.
- HTTPS uses TLS (which people tend to call SSL, which used to be correct, but is now basically a colloquial term) requires a (minimum) 3-step-handshake before even being able to communicate. HTTP skips this and goes straight to the conversation.
- Things sent over HTTPS can’t be cached anywhere in the middle. HTTP has these wonderful cache headers, which can tell anyone between the server and client keep this data, and if there’s another request for it, just return the same data again instead of going all the way to the server. Can’t happen in HTTPS because TLS is a secure connection between the client and server. Nothing in the middle can try to help because they can’t read what is being said.
- Oops, actually, this point is invalid because the test occurs without caching.
- Encryption is more expensive than not-encryption. HTTP is plain text. If you write “Hello world!” in the body, “Hello world!” is sent over the wire. HTTPS has to get translated so what it sent over the wire is secure. And so that it’s actually secure, everything sent has to be computationally-difficult to attack, which tends to mean that it’s computationally-difficult to create. (Though, this is getting easier ever since Intel started including encryption-supporting instructions on their processors).
Regardless of the technical details, HTTPS is simply more-work than HTTP and it’s counter-intuitive that doing what’s “more work” is over twice as fast.
How is this possible?
The text at the bottom of httpvshttps.com explains that the server is using SPDY.
Great. What’s SPDY?
It turns out, SPDY (pronounced “speedy”) is a protocol being developed by Google. Its goal is to reduce the latency of web pages (1). They found that there are a few places HTTP can be improved for performance (2):
- HTTP uses a single request per connection. Even though HTTP piplining exists (where one TCP connection is used to send multiple HTTP requests at once), HTTP requires the responses to be send in the order in which they were received. In addition to this, TCP’s Delayed-ACK feature waits 500ms (that’s a long time!) before sending a batched acknowledgement, preventing the connection from being used until that is received. Browsers have avoided this by opening multiple connections at once.
- Only clients initiate requests. The downside to this is that a server may know you’re going to need a resource, but it can’t provide it to you until you ask for it.
- HTTP headers are uncompressed.
- HTTP are sometimes redundant and are constantly re-sent despite never changing.
- HTTP compression is optional when really it should be required.
Cool, so what does it actually do?
SPDY adds a new session layer between SSL(TLS) and HTTP to support concurrent, interleaved streams.
Adding this layer added some nice abilities:
- Multiplexed streams
- Unlimited, concurrent streams can now occur over a single TCP connection. This resolved the HTTP/TCP issues above where HTTP must respond in order and TCP waits up to 500ms to send a delayed ACK.
- Request prioritization
- Multiplexed streams solves the problem of being able to send multiple requests over one connection but creates an issue where the bandwidth can be consumed by superfluous resource requests. To assist this issue, requests can be given a prioritization.
- HTTP header compression
- In response to the above issue, fewer bytes are transferred by always compressing HTTP headers.
- Server-initiated streams
- Push
- The server can push resources to the client that it knows they will need, before it has been requested.
- Hint
- Instead of forcibly pushing content, servers can suggest a resource be requested by the client. This gives the client the option to decide the best action (perhaps they’re on a slow or metered connection where transfer would rather be reduced until absolutely necessary.)
- Push
That’s great but wouldn’t SPDY over HTTP still be faster than SPDY over HTTPS?
As shown in the above layer diagram, SPDY is only used over SSL/TLS. So the site that kicked-off this investigation is somewhat misleading: it’s not really HTTP vs HTTPS, because if the browser only supports HTTPS without SPDY, the same results probably won’t be seen.
Haha just kidding SPDY is obsolete.
What? Yup, we’ve already moved on. HTTP2 is next big thing, which uses SPDY as a basis.
How’s the client support?
Chrome has supported SPDY basically forever. Firefox, since version 13. IE11 supports SPDY on Windows 10.
I want SPDY! What if my server software doesn’t support it?
Well here’s an awesome feature of SPDY: it just modifies how data is sent over the wire, technically the server software doesn’t have to be aware of it at all. Well, almost true. In order for SPDY to squeeze in-between the layers, which used to be accomplished via TLS’s Next Protocol Negotiation, but now uses Application-Layer Protocol Negotiation (ALPN). So servers need to support this.
Server software that already supports HTTP2
Microsoft IIS
On October 8th, 2014 the IEBlog announced the Windows 10 Technical Preview has server support for HTTP2. Currently, no other versions of IIS has support.
Apache
SPDY is supported in Apache through the mod_spdy plugin.
nginx
nginx supports SPDY draft 3.1.
How to test
Use spdycheck.org to test if a website is implementing SPDY. if it doesn’t, this site will tell you where in the steps the server failed.
Since I’m a .NET guy, I’m excited for IIS support coming up in the next version of Windows. I’m impressed with the performance improvements demonstrated by httpvshttps.com. Thanks Google!
Sources
1 – http://www.chromium.org/spdy
2 – http://www.chromium.org/spdy/spdy-whitepaper
3 – http://en.wikipedia.org/wiki/HTTP/2