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:
10
CHANGELOG
10
CHANGELOG
@@ -49,6 +49,16 @@ version 2.88
|
|||||||
in the domain it attests to be returned as unvalidated, and not
|
in the domain it attests to be returned as unvalidated, and not
|
||||||
as a validation error.
|
as a validation error.
|
||||||
|
|
||||||
|
Optimise reading large numbers of --server options. 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.
|
||||||
|
|
||||||
|
|
||||||
version 2.87
|
version 2.87
|
||||||
Allow arbitrary prefix lengths in --rev-server and
|
Allow arbitrary prefix lengths in --rev-server and
|
||||||
|
|||||||
@@ -546,11 +546,23 @@ static int order_qsort(const void *a, const void *b)
|
|||||||
return rc;
|
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 */
|
/* Must be called before add_update_server() to set daemon->servers_tail */
|
||||||
void mark_servers(int flag)
|
void mark_servers(int flag)
|
||||||
{
|
{
|
||||||
struct server *serv, **up;
|
struct server *serv, **up;
|
||||||
|
|
||||||
|
maybe_free_servers = !!flag;
|
||||||
|
|
||||||
daemon->servers_tail = NULL;
|
daemon->servers_tail = NULL;
|
||||||
|
|
||||||
/* mark everything with argument flag */
|
/* mark everything with argument flag */
|
||||||
@@ -668,6 +680,9 @@ int add_update_server(int flags,
|
|||||||
be at the end. */
|
be at the end. */
|
||||||
struct server **up, *tmp;
|
struct server **up, *tmp;
|
||||||
|
|
||||||
|
serv = NULL;
|
||||||
|
|
||||||
|
if (maybe_free_servers)
|
||||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||||
{
|
{
|
||||||
tmp = serv->next;
|
tmp = serv->next;
|
||||||
|
|||||||
@@ -5754,6 +5754,9 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
|
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* See comment above make_servers(). Optimises server-read code. */
|
||||||
|
mark_servers(0);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
|
|||||||
Reference in New Issue
Block a user