Search code examples
clibcurlnslookup

How to measure DNS lookup time in C


So I want to find out how long it takes to lookup DNS in a C program. I am using the function getaddrinfo() to do the DNS lookup so I thought I have to simply measure the time this function takes to return, in order to get the dns lookup time. However this seems to not be the case. I also have another C program that measures the DNS lookup time using libcurl and both programs return different times when looking up the same webserver at the same time.

getaddrinfo() only needs 4-5 ms to return whereas libcurl tells me that the DNS lookup took on average 15ms. I tested this both on linux and Windows and the results where similar. Something confusing to note was that getaddrinfo() returns in ~15ms when I start the program in Visual Studio release mode but once I start it from the console in ether linux or windows it has these 4-5ms times.

Also the return time of getaddrinfo remains the same (on console execution) even if I lookup a server that is far away whereas libcurl goes up to 60ms.

I can't think of anything to measure besides getaddrinfo() so my question is how to correctly measure DNS lookup in C (without help of external librarys such as libcurl)?

For reference here are the code snippets where I measure the times:

without libcurl:

    ...
    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_NUMERICSERV;
    if (prog->prog_ipver == 4)
        hints.ai_family = AF_INET;
    else if (prog->prog_ipver == 6)
        hints.ai_family = AF_INET6;

    struct timespec ts_dns_start, ts_dns_end, ts_dns_result;
    timespec_get(&ts_dns_start, TIME_UTC);

    e = getaddrinfo(host, port_str, &hints, &res);

    timespec_get(&ts_dns_end, TIME_UTC);
    timespec_diff(&ts_dns_start,&ts_dns_end, &ts_dns_result);
    printf("%.3lf;", (ts_dns_result.tv_nsec/(double) 1000000));
    ...

with libcurl

curl_global_init(CURL_GLOBAL_DEFAULT);
CURL *curl;
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
curl_easy_setopt(curl, CURLOPT_PORT, port);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 
res = curl_easy_perform(curl);
if(res == CURLE_OK)
{
    double connect_dns;
    res = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, &connect_dns);
    if(CURLE_OK == res)
    {
         printf("%.3lf" , connect_dns * 1000.0);
         ...

Solution

  • To answer my own question the problem was that libcurl standard way of resolving URL's was their threaded resolver in which the first few timeouts where too slow. Switching to the non-threaded resolver mode fixed this problem and the developers also made a fix on their github for their threaded resolver see: https://curl.haxx.se/mail/lib-2018-06/0117.html