Thursday, September 19, 2013

Prefetching dns lookups


Since I've been working hard on latency and client side performance at my company, I've been analyzing several pages a day of our site and other big sites on the web, using mainly WebPageTest, looking for ways to optimize their performance. Viewing hundreds of waterfall charts, your eyes tend to get used to looking at the same kind of patterns and the same kind of requests.

The DNS resolution, or 'DNS lookup' phase in the request was something I always thought should just be ignored. I mean, it pissed the hell out of me that it was there, but I honestly thought that there was nothing I can do about it...

A while ago I thought about simply inserting the IP addresses of our CDN domains and other sub-domains we might have directly in the code to solve this. This is bad for 2 main reasons:
1. If your IP changes for some reason it forces you to change your code accordingly. (maybe not a scenario that should happen often or even at all, but still might)
2. (and this is much more important!) When using a CDN service like akamai, the dns lookup will give you different results according to where you are in the world. Since they have servers strategically placed in different geographical locations, a user from the USA will probably get a different IP than a user from Europe or Asia.

Well, recently that all changed - I realized that you can direct the browser to prefetch the dns lookup at the beginning of the request, so that when the browser runs into the new domain it won't have to lookup up the dns again.

To do this, all you need to add is this tag at the beginning of your page :


Doing this on the domain you're currently on has no effect since the browser already did the dns lookup, but it can help when you know that in your page source you have calls to multiple sub-domains (for cdn's), calls to 3rd party libraries or ajax calls you make to other domains. Even if you know of a call that will happen on the next page the user lands on, you should still prefetch the dns lookup since the browser caches the results for a couple of minutes at least, and this should have no effect on the current page performance.

The most common response I get when telling people about this, or reading about this on the internet is that the DNS lookup alone doesn't take that long. From my tests, I can say that the average DNS lookup time is under 100ms, although usually above 20ms, and sometimes it passes the 100ms. Even though this isn't the common case, you can still make sure time is saved for those 'unlucky' users.
...and besides, this is one of the easiest performance wins you have - It requires almost no work to implement!

Just while writing this article I happened to test facebook.com, and check out how long the DNS lookup took on those 3 last requests!
(You can view the full results of this test here : http://www.webpagetest.org/result/130919_17_B60/1/details/) Yep, you better believe your eyes - The DNS lookup on those last requests seemed to take 2 seconds!!
Now, I don't know why they took 2 seconds in that case, and I bet this is really rare, but it still happens sometimes, you can't argue with that.
But hey, If they would've requested to prefetch that last domain, it would still take that long! That's right, but it would've started much earlier, and could've still save hundreds of valuable milliseconds.

So, my suggestions to you is, lets say you have 4 sub-domains for CDN's and you know you're going to call facebook's api at some point, you should put something like this in the head tag of your source :







This will tell the browser to immediately start the dns fetching so that when the browser reaches those domains it will have the ip stored in the cache already.

If you want to see what it looks like when you're prefetching the dns lookup properly, take a look at these WebPageTest results from amazon : http://www.webpagetest.org/result/130919_ZQ_J6V/1/details/
You can clearly see that the dns lookup part of the request on some of the domains happen a lot before the browser reaches the actual resource on the timeline, and when it does, it doesn't need to wait for the dns lookup.
As usual, great work amazon! :)


Some more resources on the subject :
- MDN - Controlling DNS prefetching
- Chromium Blog - DNS prefetching
- Performance Calendar - Speed up your site using DNS prefetching

4 comments:

  1. There are still DNS lookups for the 2 first hits to the CDN in your example: http://www.webpagetest.org/result/130919_ZQ_J6V/1/details/.
    g-ecx.images-amazon.com: DNS Lookup: 51 ms
    z-ecx.images-amazon.com: DNS Lookup: 44 ms

    ReplyDelete
    Replies
    1. The DNS lookup will always happen no matter what (when using domain name, and not a direct IP address), but it's a matter of when it will happen. Since the call to z-ecx.images-amazon.com is one of the first calls, then it happens at the beginning of the call and nothing is really 'saved'.
      If you closely look at the first call to g-ecx.amazon-images.com, then you will see that the DNS lookup happened a little before the call to the first resource file. (It started happening the same moment the dns lookup to z-ecx.amazon-images.com happened)

      Delete
  2. Dumps collection is the website that deals in preparation material for the exam for many years. According to my exposure and research, this is the right platform where you can get exact exam dumps. MB6-894 exam questions answers

    ReplyDelete