From: Stefan Fritsch Date: Sat, 2 Oct 2010 14:44:20 +0000 (+0000) Subject: core: Speed up config parsing if using a very large number of config X-Git-Tag: 2.3.9~373 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=049ba34b53b9c81125aeecffd0abbf97281b5bc7;p=apache core: Speed up config parsing if using a very large number of config files PR: 50002 Submitted by: andrew cloudaccess net git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1003808 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index c6b02a24f9..cb7d447b18 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,9 @@ Changes with Apache 2.3.9 Fix a denial of service attack against mod_reqtimeout. [Stefan Fritsch] + *) core: Speed up config parsing if using a very large number of config + files. PR 50002 [andrew cloudaccess net] + *) mod_cache: Support the caching of HEAD requests. [Graham Leggett] *) htcacheclean: Allow the option to round up file sizes to a given diff --git a/include/ap_mmn.h b/include/ap_mmn.h index f44a22beb7..5207637423 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -272,6 +272,7 @@ * 20100923.1 (2.3.9-dev) Add cache_status hook. * 20100923.2 (2.3.9-dev) Add generate_log_id hook. * Make root parameter of ap_expr_eval() const. + * 20100923.3 (2.3.9-dev) Add "last" member to ap_directive_t */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -279,7 +280,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20100923 #endif -#define MODULE_MAGIC_NUMBER_MINOR 2 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 3 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/util_cfgtree.h b/include/util_cfgtree.h index 4da4c7dd1d..791a5cc16c 100644 --- a/include/util_cfgtree.h +++ b/include/util_cfgtree.h @@ -64,6 +64,13 @@ struct ap_directive_t { const char *filename; /** The line number the directive was on */ int line_num; + + /** A short-cut towards the last directive node in the tree. + * The value may not always be up-to-date but it always points to + * somewhere in the tree, nearer to the tail. + * This value is only set in the first node + */ + struct ap_directive_t *last; }; /** diff --git a/server/config.c b/server/config.c index dc9b3b64a4..a3d67f0b1d 100644 --- a/server/config.c +++ b/server/config.c @@ -1284,11 +1284,30 @@ AP_DECLARE(const char *) ap_build_config(cmd_parms *parms, ap_directive_t *curr_parent = NULL; char *l = apr_palloc (temp_pool, MAX_STRING_LEN); const char *errmsg; + ap_directive_t **last_ptr = NULL; + + if(current) { + /* If we have to traverse the whole tree again for every included + * config file, the required time grows as O(n^2) with the number of + * files. This can be a significant delay for large configurations. + * Therefore we cache a pointer to the last node. + */ + last_ptr = &(current->last); + + if(last_ptr && *last_ptr) { + current = *last_ptr; + } + } if (current != NULL) { while (current->next) { current = current->next; } + + if(last_ptr) { + /* update cached pointer to last node */ + *last_ptr = current; + } } while (!(ap_cfg_getline(l, MAX_STRING_LEN, parms->config_file))) {