Is asychronous DNS lookup worth keeping at all?
Eric S. Raymond
esr at thyrsus.com
Wed Dec 2 14:03:52 UTC 2015
Hal Murray <hmurray at megapathdsl.net>:
> >> There is a lot of interest in getting servers restarted quickly. Telling
> >> all those users they can't use any non-local server names seems unwise.
>
> > That's not the implication. If we removed asynchronous lookup, they'd
> > only incur an additional initial start time cost for using *more than
> > one* named server. The cost for using just one wouldn't change.
>
> I can't figure out how you are thinking ntpd works. I'm not sure I know how
> it does work.
We need to have this conversation so I can get the tour document right. :-)
Here's what I think is going on in the 1-hostname case with asynch DNS:
1. ntpd starts up.
2. getaddrinfo_sometime() is called during argument or config parsing.
It spawns one worker thread.
3. Main receive loop, where it's iterating over all UDP sockets looking for
incoming packets, begins in the main thread. No sockets are open.
4. Sometime later, the callback passed to getaddrinfo_sometime is called and the
numeric IP for the hostname becomes available. A UDP socket is activated.
Protocol engine ships the first query to the server (or pool whatsis)
at the other end of the socket.
5. Sometime after this, enough responses come in for time sync.
If DNS lookup is synchronous, the sequences is different.
1. ntpd starts up.
2. getaddrinfo() is called during argument or config parsing. It blocks
until it returns a numeric IP. The UDP socket is created immediately.
The socket list is nonempty.
3. Main receive loop, where it's iterating over all UDP sockets looking for
incoming packets, begins. Because the socket list is nonempty
the protocol engine ships the first query immediately.
4. Sometime after this, enough responses come in for time sync.
The point is, in both cases no query can be shipped to the server
until the getaddrinfo() returns a result. That delay is independent
of whether the lookup runs in its own thread or the main thread.
Now suppose there are two hostnames. Asynchronous:
1. ntpd starts up.
2. getaddrinfo() is called twice during argument or config parsing.
It launches two worker threads.
3. Main receive loop, where it's iterating over all UDP sockets looking for
incoming packets, begins in the main thread. No sockets are open.
4. Sometime later, the callback passed to getaddrinfo_sometime is called and the
numeric IP for one hostname becomes available. A UDP socket is opened
and the protocol engine ships a query to the server (or pool whatsis)
at the other end of the association.
5. Sometime after this, enough responses come in for time sync. The minimum
delay was bounded below by the time for the first DNS-lookup callback to
fire.
6. Sometime after this, the callback for the *second* lookup fires. Another
UDP socket is added to the list and another query shipped. At this point
we might already have time sync from the first server.
Synchronous
1. ntpd starts up.
2. getaddrinfo() is called twice during argument or config parsing. The calls
blocks sequentially until they return two numeric IPs. The UDP sockets are
created immediately; we have paid the latency cost for both calls
rather than just one. The socket list is nonempty.
3. Main receive loop, where it's iterating over all UDP sockets looking for
incoming packets, begins. Because the socket list is nonempty
the protocol engine ships the first two queries immediately.
4. Sometime after this, enough responses come in for time sync.
If I understand all this correctly (and maybe I don't), the latency
cost of both cases is bounded below by the cost of the first DNS lookup.
The difference is that in the synchronous case you also have to wait for
the *second* lookup.
--
<a href="http://www.catb.org/~esr/">Eric S. Raymond</a>
More information about the devel
mailing list