I recently analyzed a secure web page that took 20 seconds till the onLoad event triggered. Once on the site – interacting with the site was slow as well – especially when dealing with dynamic content like the auto completion for the search field or dynamic popup menus.
HTTP vs. HTTPS
Secure connections in web applications are a necessity when dealing with sensitive data such as your financial information in your online banking system or your customer data in your online CRM. To secure the transferred content between your web server and the browser you use HTTPS. There is obviously overhead involved when establishing a secure connection vs a plain HTTP connection. In order to keep the overhead as low as possible for your web site you have to understand some of the underlying basics.
What it takes to download secure content by the browser?
Every browser has multiple physical connections per domain that are used to download the initial HTML page and then all the referenced embedded objects. The number of physical connection depends on the browser version. Each physical connection needs to establish the connection to the web server. In case it is a secure connection it requires an SSL Handshake as explained in the following blog post: The SSL Handshake.
As long as the connection is kept alive – secure communication is possible without additional handshaking. Once a connection is closed (e.g.: forced by the server) the browser needs to reconnect for the next request including the costly SSL Handshake.
The browser is also using different physical connections for different domains – meaning – that static content (images, scripts, css, …) that is delivered from a different domain must establish its own connection. If these objects are also served secure (intentional or not) you have to deal with the extra handshake cost.
Lets have a look at a sample page and all its depending requests and lets see how many SSL handshakes are necessary:
https://www.mydomain.com -> 1st phys. connection on www.mydomain.com – 1st handshake
https://www.mydomain.com/logo.png -> reuse 1st phys. connection -> no handshake
https://www.mydomain.com/background.png -> 2nd phys. connection to www.mydomain.com – 2nd handshake
https://image1.mydomain.com/image1.gif -> 1st phys connection on image1.mydomain.com -> 3rd handshake
https://image1.mydomain.com/image2.gif -> 2nd phys connection on image1.mydomain.com -> 4th handshake
https://image1.mydomain.com/image3.gif -> reuse 1st phys connection -> no handshake
https://ssl.google-analytics/siteopt.js=… -> 1st phys connection on ssl.google-analytics.com -> 5th handshake
https://scripts.mycdn.com/main.js -> 1st phys connection on scripts.mycdn.com -> 6th handshake
I guess you see that there is a lot of handshaking going on that you may not be aware of. The example above shows a browser with 2 physical connections. In case you deal with a browser that uses more than 2 connections, image3.gif would also need to do an SSL handshake.
Considerations when using HTTPS
There are different things to consider in order to not run into HTTPS related performance problems. Some of these considerations are also valid for non-HTTPS applications but result in a higher performance hit due to the handshaking overhead. The problem that I described in the intro section boiled down to be caused by the web server that forced the browser to close the connection after every request resulting in SSL handshakes for every request that was still to come. There are other – more generic things that you should consider that can speed up your website performance. Let’s take a closer look by starting with the problem I had.
Use Connection Keep-Alive
Using the Dynatrace AJAX Edition I analyzed the URL in question and was surprised to see the following Summary View
The Page Load Time column tells me the time until the onLoad event was triggered for this URL. The Network Pie Chart shows me all the network activity on that page (also activity that happened after the onLoad event was triggered) divided into Connection Time, Server Busy and actual Transfer time. And this is where it gets interesting. On the total page I had 24 seconds spent in establishing the physical network connection. Why is that? How can an SSL handshake take that long?
Drilling from here into the Network View showed me each individual Network Request and how much time was spent on the individual tasks (Connect, Transfer, Server, Wait):
This view shows me that almost every request (except those that came from the local browser cache) had to take a huge hit in network connection time. The connection time for each single network request ranges from 0.5 to 1.1 seconds. If you sum that up you get to the very slow page load time. But why is that?
The solution to this problem is to enable connection keep-alive on the web server so that the browser can send subsequent requests on the same established SSL connection.
General Optimization Rules
There are many general optimization rules that obviously help here as well. Like – limiting the number of web requests, using CDNs (Content Delivery Networks), using client side caching, avoid redirects, …
For a complete list check out the Best Practices for Speeding Up Your Web Site
Use Domain Sharding for HTTPS scenarios?
What are your thoughts on that topic? What about using mixed content? Meaning – using HTTPS for secure content and HTTP for insecure content (like images, scripts …) on the same page? You probably end up with many warning messages in the browser – but would this be something to accept to gain faster page speed? Let me know your thoughts.