gethostbyname vs getaddrinfo

Summary

Performance tests demonstrate that getaddrinfo is significantly slower than gethostbyname for domain name resolution. This performance difference stems from getaddrinfo's default behavior of resolving both IPv4 and IPv6 addresses, leading to ten DNS server communications compared to gethostbyname's two. However, configuring getaddrinfo to resolve only IPv4 addresses matches the speed of gethostbyname, an older function that lacks native IPv6 support, addressed by gethostbyname2. While getaddrinfo is generally recommended for its comprehensive capabilities, developers requiring non-blocking resolution should explore alternatives like the C-ares library.

getaddrinfo is slower than ping when resolving domain names. I think ping uses gethostbyname to resolve a domain name. The question becomes whether getaddrinfo is slower than gethostbyname. After testing with both functions, we find that getaddrinfo is really slow compared to gethostbyname. By strace tracking,  we find getaddrinfo will communicate with DNS server 10 times and gethostbyname will communicate with DNS server communication twice.

gethostbyname is an old way to resolve domain name, The disadvantage of it is that it does not support IPV6, so there is a gethostbyname2 which replaces gethostbyname, it supports both IPV4 and IPV6 resolving. Textbooks recommend to use getaddrinfo. The reason why it is slow is that getaddrinfo will resolve both IPV6 and IPv4 by default. If you set getaddrinfo only to resolve IPV4, the speed is the same as gethostbyname , it will communicate with DNS server twice

gethostbyname and getaddrinfo are bothworking in  blocked mode, C-ares library can be used to achieve asynchronous resolving.

When calling gethostbyname2 twice, respectively resolving IPV6 and IPv4, it's the equivalent of one call to getaddrinfo.

Testing code :

#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
 
#define HOST "cet.99sushe.com"
 
void print_time(const char *tip, const struct timeval *begin, const struct timeval *end)
{
    long diff = (end->tv_sec - begin->tv_sec) * 1000000 +
        (end->tv_usec - begin->tv_usec);
 
    printf("%s: %ld.%ld\n", tip, diff / 1000000, diff % 10000);
}
 
int main(int argc, char *argv[])
{
    struct timeval begin;
    struct timeval end;
 
    if (argc == 2 && strcmp(argv[1], "getaddrinfo") == 0) {
        struct addrinfo *ai;
        struct addrinfo hints;
 
        memset(&hints, 0x00, sizeof(hints));
        hints.ai_family   = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = 0;
        hints.ai_flags    = AI_NUMERICSERV;
 
        gettimeofday(&begin, 0);
        getaddrinfo(HOST, "80", &hints, &ai);
        gettimeofday(&end, 0);
 
        print_time("getaddrinfo", &begin, &end);
    }
 
    if (argc == 2 && strcmp(argv[1], "gethostbyname") == 0) {
        gettimeofday(&begin, 0);
        gethostbyname2(HOST, AF_INET);
        gethostbyname2(HOST, AF_INET6);
        gettimeofday(&end, 0);
 
        print_time("gethostbyname", &begin, &end);
    }
 
    return 0;
}
 
C++ NETWORK DNS

  RELATED

  COMMENTS

0

No comment for this article.