【问题标题】:How to measure DNS lookup time in C如何在 C 中测量 DNS 查找时间
【发布时间】:2018-06-11 15:11:56
【问题描述】:

所以我想知道在 C 程序中查找 DNS 需要多长时间。 我正在使用函数 getaddrinfo() 进行 DNS 查找,所以我认为我必须简单地测量该函数返回所需的时间,以便获得 dns 查找时间。 然而,情况似乎并非如此。 我还有另一个使用 libcurl 测量 DNS 查找时间的 C 程序,两个程序在同时查找同一个网络服务器时返回不同的时间。

getaddrinfo() 只需要 4-5 毫秒即可返回,而 libcurl 告诉我 DNS 查找平均需要 15 毫秒。我在 linux 和 Windows 上都对此进行了测试,结果相似。 需要注意的是,当我在 Visual Studio 发布模式下启动程序时,getaddrinfo() 在大约 15 毫秒内返回,但是一旦我从 ether linux 或 Windows 中的控制台启动它,它就会有 4-5 毫秒的时间。

getaddrinfo 的返回时间也保持不变(在控制台执行时),即使我查找的服务器距离很远,而 libcurl 的时间达到 60 毫秒。

除了 getaddrinfo() 之外,我想不出任何要衡量的东西,所以我的问题是如何正确衡量 C 中的 DNS 查找(不借助 libcurl 等外部库)?

这里是我测量时间的代码 sn-ps 供参考:

没有 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));
    ...

使用 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);
         ...

【问题讨论】:

  • 名称查找通常由操作系统或系统服务/守护程序执行并在本地缓存。如果它们没有在本地缓存,它们可能仍会缓存在您配置的任何 DNS 服务器上(例如,如果您使用的是由您的 ISP 运行的服务器)。如果您想要可重现的测试,您至少需要了解如何清除本地缓存。
  • 在您的两个示例中尝试valgrind --tool=callgrind <program>,看看它显示了什么。这可以让您了解getaddrinfo 返回后发生的情况。我怀疑 vararg 函数 curl_easy_getinfo 除了做一个简单的查找之外还做了很多事情。
  • 感谢您提供有关缓存的提示。我不认为这是这里的问题(我手动清除了缓存,它并没有影响结果)但这绝对是我从现在开始要记住的事情。

标签: c libcurl nslookup


【解决方案1】:

要回答我自己的问题,问题是 libcurl 解析 URL 的标准方法是他们的线程解析器,其中前几次超时太慢了。 切换到非线程解析器模式解决了这个问题,开发人员还在他们的 github 上为他们的线程解析器进行了修复,请参阅:https://curl.haxx.se/mail/lib-2018-06/0117.html

【讨论】:

  • “睡眠定时器没有足够积极地增加”并不能真正解释问题(我知道你是从链接的邮件中复制的,这不是你自己的措辞)。是前几次超时太慢,而不是后期超时的退避率太高或太低。
  • 我改写了。现在看起来好多了?
猜你喜欢
  • 1970-01-01
  • 2011-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多