If you think about the load time of your web page, you often think only of bandwidth, image size. But latency is becoming a more critical factor than bandwidth, and, is much harder to solve. Latency occurs due to the speed of light, hand off between systems, etc. The worst kinds of latency are ones that are round-trip: a request needing a response before you can continue. And one of these is DNS latency, the name lookup to IP we rely on daily.
Earlier I wrote about The Quest For Web Site Performance Perfection and Latency And Load Testing Your Web Site With Locusst and Istio. Those showed how we could load a web site down, and how we could assess how good it is, areas to improve.
Today lets use a tool from Pingdom for performance testing (you can also use Lighthouse which is built into Chrome). It gives us a nice shiny letter-grade score, but also some details. Here we can see to load the Agilicus web site took 830KB, 600ms, and 32 requests. Its these last two that will help the most in optimisation as we examine DNS latency.
If we look at the Gantt chart, we can see that there is a set of blocking activities before we get going. They are:
- DNS Latency Lookup (71ms)
- SSL Handshake (20ms)
- HTTP Connect (36ms)
- Send Request (0.1ms)
- Wait for response (23ms)
The largest times here are before we even get to the HTML. 140ms before our server even gets the GET. How can we improve?
Some would say get rid of the SSL. If this is you, read this page. “Is TLS Fast Yet“. And then read about 0-RTT TLS. These are trying to get the overhead of TLS (SSL) to 0.
But what about DNS latency? Its our top item. In this case, our DNS is run on Google DNS. The Browser emits a request to its recursive DNS (the one on your PC). The recursive DNS, if not in the cache, goes to (usually) another recursive, e.g. the one in your Router. This in turn usually goes to another recursive DNS (e.g. your ISP). This in turn may need to consult the root to find the origin server, and request. Each of those hand offs takes time. But also, we’ve gone to all the trouble to encrypt our traffic, and now we are sending unencrypted DNS around broadcasting what we are doing. Hmm.
We can improve things a little bit. We can’t do much about the first page, but if we use other sites (e.g. CDN, images, etc), we can add a prefetch tag:
<link rel="dns-prefetch" href="https://images.mysite.ca" >
Now, this only makes sense if its cross-origin (e.g. to another site), not to your own. Also, we might consider addign a preconnect in (since that will help get the TLS live):
<link rel="preconnect" href="https://images.mysite.ca/" crossorigin> <link rel="dns-prefetch" href="https://images.mysite.ca/">
But, here, on my web site, those preconnect/dns-prefetch will not do anything, since I serve all my “above the fold blocking” content from a single domain. Worse, the time seems to vary quite a bit, this run was 90ms for the DNS.
If my hostname were a CNAME, I could consider removing that and making it an A record, to avoid a DNS latency lookup. But its not.
If we look at solvedns.com dnsspeedtools, we can see that our authoritative (ns-cloud-d1.googledomains.com) is going to be ~40ms. A lot of that will be the ~15ms each way for the request-response round trip. So there is not much we can do.
So, is there a solution to initial DNS latency? It seems not, other than I suppose using an IP address instead of a host name. This works if your are Cloudflare with https://1.1.1.1/ but for the rest of us, its not very feasible. The DNS authoritative I use is already well-sinked and well-peered around the world.