mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Optimise readng large number --server options at start up.
When re-reading upstream servers from /etc/resolv.conf or other sources that can change dnsmasq tries to avoid memory fragmentation by re-using existing records that are being re-read unchanged. This involves seaching all the server records for each new one installed. During startup this search is pointless, and can cause long start times with thousands of --server options because the work needed is O(n^2). Handle this case more intelligently. Thanks to Ye Zhou for spotting the problem and an initial patch.
This commit is contained in:
@@ -546,11 +546,23 @@ static int order_qsort(const void *a, const void *b)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* When loading large numbers of server=.... lines during startup,
|
||||
there's no possibility that there will be server records that can be reused, but
|
||||
searching a long list for each server added grows as O(n^2) and slows things down.
|
||||
This flag is set only if is known there may be free server records that can be reused.
|
||||
There's a call to mark_servers(0) in read_opts() to reset the flag before
|
||||
main config read. */
|
||||
|
||||
static int maybe_free_servers = 0;
|
||||
|
||||
/* Must be called before add_update_server() to set daemon->servers_tail */
|
||||
void mark_servers(int flag)
|
||||
{
|
||||
struct server *serv, **up;
|
||||
|
||||
maybe_free_servers = !!flag;
|
||||
|
||||
daemon->servers_tail = NULL;
|
||||
|
||||
/* mark everything with argument flag */
|
||||
@@ -667,27 +679,30 @@ int add_update_server(int flags,
|
||||
and move to the end of the list, for order. The entry found may already
|
||||
be at the end. */
|
||||
struct server **up, *tmp;
|
||||
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
{
|
||||
tmp = serv->next;
|
||||
if ((serv->flags & SERV_MARK) &&
|
||||
hostname_isequal(alloc_domain, serv->domain))
|
||||
{
|
||||
/* Need to move down? */
|
||||
if (serv->next)
|
||||
{
|
||||
*up = serv->next;
|
||||
daemon->servers_tail->next = serv;
|
||||
daemon->servers_tail = serv;
|
||||
serv->next = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
}
|
||||
|
||||
serv = NULL;
|
||||
|
||||
if (maybe_free_servers)
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
{
|
||||
tmp = serv->next;
|
||||
if ((serv->flags & SERV_MARK) &&
|
||||
hostname_isequal(alloc_domain, serv->domain))
|
||||
{
|
||||
/* Need to move down? */
|
||||
if (serv->next)
|
||||
{
|
||||
*up = serv->next;
|
||||
daemon->servers_tail->next = serv;
|
||||
daemon->servers_tail = serv;
|
||||
serv->next = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
}
|
||||
|
||||
if (serv)
|
||||
{
|
||||
free(alloc_domain);
|
||||
|
||||
@@ -5753,7 +5753,10 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
#endif
|
||||
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
|
||||
#endif
|
||||
|
||||
|
||||
/* See comment above make_servers(). Optimises server-read code. */
|
||||
mark_servers(0);
|
||||
|
||||
while (1)
|
||||
{
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
|
||||
Reference in New Issue
Block a user