From d9fdeae6a476d9fb0a1eb0c6147fc81e32056e42 Mon Sep 17 00:00:00 2001 From: Sean Bright Date: Fri, 1 Dec 2017 11:01:01 -0500 Subject: [PATCH] config: Speed up config template lookup ast_category_get() has an (undocumented) implementation detail where it tries to match the category name first by an explicit pointer comparison and if that fails falls back to a normal match. When initially building an ast_config during ast_config_load, this pointer comparison can never succeed, but we will end up iterating all categories twice. As the number of categories using a template increases, this dual looping becomes quite expensive. So we pass a flag to category_get_sep() indicating if a pointer match is even possible before trying to do so, saving us a full pass over the list of current categories. In my tests, loading a file with 3 template categories and 12000 additional categories that use those 3 templates (this file configures 4000 PJSIP endpoints with AOR & Auth) takes 1.2 seconds. After this change, that drops to 22ms. Change-Id: I59b95f288e11eb6bb34f31ce4cc772136b275e4a --- main/config.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/main/config.c b/main/config.c index 3d8dcfb3d7..a76d0870ca 100644 --- a/main/config.c +++ b/main/config.c @@ -986,13 +986,15 @@ struct ast_category *ast_category_new_template(const char *name, const char *in_ } static struct ast_category *category_get_sep(const struct ast_config *config, - const char *category_name, const char *filter, char sep) + const char *category_name, const char *filter, char sep, char pointer_match_possible) { struct ast_category *cat; - for (cat = config->root; cat; cat = cat->next) { - if (cat->name == category_name && does_category_match(cat, category_name, filter, sep)) { - return cat; + if (pointer_match_possible) { + for (cat = config->root; cat; cat = cat->next) { + if (cat->name == category_name && does_category_match(cat, category_name, filter, sep)) { + return cat; + } } } @@ -1008,7 +1010,7 @@ static struct ast_category *category_get_sep(const struct ast_config *config, struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name, const char *filter) { - return category_get_sep(config, category_name, filter, ','); + return category_get_sep(config, category_name, filter, ',', 1); } const char *ast_category_get_name(const struct ast_category *category) @@ -1792,7 +1794,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, if (cur[1] != ',') { filter = &cur[1]; } - *cat = category_get_sep(cfg, catname, filter, '&'); + *cat = category_get_sep(cfg, catname, filter, '&', 0); if (!(*cat)) { if (newcat) { ast_category_destroy(newcat); @@ -1810,7 +1812,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat, } else { struct ast_category *base; - base = ast_category_get(cfg, cur, "TEMPLATES=include"); + base = category_get_sep(cfg, cur, "TEMPLATES=include", ',', 0); if (!base) { if (newcat) { ast_category_destroy(newcat);