File 0018-Optimize-finding-a-module.-ap_find_linked_module-was.patch of Package ea-apache2
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "J. Nick Koston" <nick@cpanel.net>
Date: Fri, 13 Dec 2019 10:57:41 -0600
Subject: [PATCH 18/21] Optimize finding a module. ap_find_linked_module was
not performing well when there a lot of IfModule statements in httpd.conf.
This change uses a hash to keep track of modules which cut the startup time
from 3s to 1.5s on a large configuration file. This also makes find_module
module simpler.
---
server/config.c | 37 +++++++++++++++++++++++++++++--------
server/core.c | 42 +-----------------------------------------
2 files changed, 30 insertions(+), 49 deletions(-)
diff --git a/server/config.c b/server/config.c
index 3d11ff5..62421b9 100644
--- a/server/config.c
+++ b/server/config.c
@@ -229,6 +229,7 @@ AP_DECLARE_DATA module *ap_top_module = NULL;
AP_DECLARE_DATA module **ap_loaded_modules=NULL;
static apr_hash_t *ap_config_hash = NULL;
+static apr_hash_t *ap_module_hash = NULL;
/* a list of the module symbol names with the trailing "_module"removed */
static char **ap_module_short_names = NULL;
@@ -513,9 +514,13 @@ static void rebuild_conf_hash(apr_pool_t *p, int add_prelinked)
module **m;
ap_config_hash = apr_hash_make(p);
+ ap_module_hash = apr_hash_make(p);
apr_pool_cleanup_register(p, &ap_config_hash, ap_pool_cleanup_set_null,
apr_pool_cleanup_null);
+ apr_pool_cleanup_register(p, &ap_module_hash, ap_pool_cleanup_set_null,
+ apr_pool_cleanup_null);
+
if (add_prelinked) {
for (m = ap_prelinked_modules; *m != NULL; m++) {
ap_add_module_commands(*m, p);
@@ -526,9 +531,11 @@ static void rebuild_conf_hash(apr_pool_t *p, int add_prelinked)
static void ap_add_module_commands(module *m, apr_pool_t *p)
{
apr_pool_t *tpool;
+ apr_pool_t *mpool;
ap_mod_list *mln;
const command_rec *cmd;
char *dir;
+ char *module_identifier;
cmd = m->cmds;
@@ -537,6 +544,15 @@ static void ap_add_module_commands(module *m, apr_pool_t *p)
}
tpool = apr_hash_pool_get(ap_config_hash);
+ apr_hash_set(ap_module_hash, m->name, APR_HASH_KEY_STRING, m);
+
+ /* We need to add the module identifier so both <IfModule mod_ssl.c> and <IfModule ssl_module> work */
+ if (ap_module_short_names[m->module_index]) {
+ mpool = apr_hash_pool_get(ap_module_hash);
+ /* ap_module_short_names has the trailing "_module" removed so we have to put it back */
+ module_identifier = apr_pstrcat(mpool, ap_module_short_names[m->module_index], "_module", NULL);
+ apr_hash_set(ap_module_hash, module_identifier, APR_HASH_KEY_STRING, m);
+ }
while (cmd && cmd->name) {
mln = apr_palloc(tpool, sizeof(ap_mod_list));
@@ -662,6 +678,8 @@ AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p,
AP_DECLARE(void) ap_remove_module(module *m)
{
module *modp;
+ apr_pool_t *mpool;
+ char *module_identifier;
modp = ap_top_module;
if (modp == m) {
@@ -690,6 +708,16 @@ AP_DECLARE(void) ap_remove_module(module *m)
modp->next = modp->next->next;
}
+ apr_hash_set(ap_module_hash, m->name, APR_HASH_KEY_STRING, NULL);
+
+ /* We need to remove the module identifier so both <IfModule mod_ssl.c> and <IfModule ssl_module> work */
+ if (ap_module_short_names[m->module_index]) {
+ mpool = apr_hash_pool_get(ap_module_hash);
+ /* ap_module_short_names has the trailing "_module" removed so we have to put it back */
+ module_identifier = apr_pstrcat(mpool, ap_module_short_names[m->module_index], "_module", NULL);
+ apr_hash_set(ap_module_hash, module_identifier, APR_HASH_KEY_STRING, NULL);
+ }
+
free(ap_module_short_names[m->module_index]);
ap_module_short_names[m->module_index] = NULL;
merger_func_cache[m->module_index] = NULL;
@@ -829,14 +857,7 @@ AP_DECLARE(const char *) ap_find_module_short_name(int module_index)
AP_DECLARE(module *) ap_find_linked_module(const char *name)
{
- module *modp;
-
- for (modp = ap_top_module; modp; modp = modp->next) {
- if (strcmp(modp->name, name) == 0)
- return modp;
- }
-
- return NULL;
+ return apr_hash_get(ap_module_hash, name, APR_HASH_KEY_STRING);
}
/*****************************************************************
diff --git a/server/core.c b/server/core.c
index 900606f..481da18 100644
--- a/server/core.c
+++ b/server/core.c
@@ -2811,47 +2811,7 @@ static const char *ifsection(cmd_parms *cmd, void *mconfig, const char *arg)
static module *find_module(server_rec *s, const char *name)
{
- module *found = ap_find_linked_module(name);
-
- /* search prelinked stuff */
- if (!found) {
- ap_module_symbol_t *current = ap_prelinked_module_symbols;
-
- for (; current->name; ++current) {
- if (!strcmp(current->name, name)) {
- found = current->modp;
- break;
- }
- }
- }
-
- /* search dynamic stuff */
- if (!found) {
- APR_OPTIONAL_FN_TYPE(ap_find_loaded_module_symbol) *check_symbol =
- APR_RETRIEVE_OPTIONAL_FN(ap_find_loaded_module_symbol);
-
- if (check_symbol) {
- /*
- * There are two phases where calling ap_find_loaded_module_symbol
- * is problematic:
- *
- * During reading of the config, ap_server_conf is invalid but s
- * points to the main server config, if passed from cmd->server
- * of an EXEC_ON_READ directive.
- *
- * During config parsing, s may be a virtual host that would cause
- * a segfault in mod_so if passed to ap_find_loaded_module_symbol,
- * because mod_so's server config for vhosts is initialized later.
- * But ap_server_conf is already set at this time.
- *
- * Therefore we use s if it is not virtual and ap_server_conf if
- * s is virtual.
- */
- found = check_symbol(s->is_virtual ? ap_server_conf : s, name);
- }
- }
-
- return found;
+ return ap_find_linked_module(name);
}
/* Callback function type used by start_cond_section. */