[svn-commits] file: branch 13 r431841 - /branches/13/res/res_sorcery_config.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Sun Feb 15 11:42:38 CST 2015


Author: file
Date: Sun Feb 15 11:42:34 2015
New Revision: 431841

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=431841
Log:
res_sorcery_config: Improve object lookup times.

The res_sorcery_config module currently uses a fixed bucket
size of 53. This means that depending on the number of objects
you either end up with excess buckets or a lot of collisions.
Due to the way that res_sorcery_config is implemented it's actually
possible to make the bucket size dynamic based on the number of
objects. This is due to the fact that each loading of the config file
produces a new container and does not modify the existing one.
This change uses the number of expected objects and finds a prime
number near it. In practice depending on the number of objects this
can speed up lookups anywhere from 2X to 15X. This change also removes
the lock from the container as it is not needed.

Review: https://reviewboard.asterisk.org/r/4423/

Modified:
    branches/13/res/res_sorcery_config.c

Modified: branches/13/res/res_sorcery_config.c
URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_sorcery_config.c?view=diff&rev=431841&r1=431840&r2=431841
==============================================================================
--- branches/13/res/res_sorcery_config.c (original)
+++ branches/13/res/res_sorcery_config.c Sun Feb 15 11:42:34 2015
@@ -39,9 +39,7 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/config.h"
 #include "asterisk/uuid.h"
-
-/*! \brief Default number of buckets for sorcery objects */
-#define DEFAULT_OBJECT_BUCKETS 53
+#include "asterisk/hashtab.h"
 
 /*! \brief Structure for storing configuration file sourced objects */
 struct sorcery_config {
@@ -183,7 +181,7 @@
 	struct sorcery_config *config = data;
 	RAII_VAR(struct ao2_container *, objects, ao2_global_obj_ref(config->objects), ao2_cleanup);
 
-	return objects ? ao2_find(objects, id, OBJ_KEY | OBJ_NOLOCK) : NULL;
+	return objects ? ao2_find(objects, id, OBJ_KEY) : NULL;
 }
 
 static void sorcery_config_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
@@ -237,6 +235,7 @@
 	struct ast_category *category = NULL;
 	RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
 	const char *id = NULL;
+	unsigned int buckets = 0;
 
 	if (!cfg) {
 		ast_log(LOG_ERROR, "Unable to load config file '%s'\n", config->filename);
@@ -249,7 +248,37 @@
 		return;
 	}
 
-	if (!(objects = ao2_container_alloc(config->buckets, sorcery_config_hash, sorcery_config_cmp))) {
+	if (!config->buckets) {
+		while ((category = ast_category_browse_filtered(cfg, NULL, category, NULL))) {
+
+			/* If given criteria has not been met skip the category, it is not applicable */
+			if (!sorcery_is_criteria_met(ast_category_first(category), config->criteria)) {
+				continue;
+			}
+
+			buckets++;
+		}
+
+		/* Determine the optimal number of buckets */
+		while (buckets && !ast_is_prime(buckets)) {
+			/* This purposely goes backwards to ensure that the container doesn't have a ton of
+			 * empty buckets for objects that will never get added.
+			 */
+			buckets--;
+		}
+
+		if (!buckets) {
+			buckets = 1;
+		}
+	} else {
+		buckets = config->buckets;
+	}
+
+	ast_debug(2, "Using bucket size of '%d' for objects of type '%s' from '%s'\n",
+		buckets, type, config->filename);
+
+	if (!(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, buckets,
+		sorcery_config_hash, sorcery_config_cmp))) {
 		ast_log(LOG_ERROR, "Could not create bucket for new objects from '%s', keeping existing objects\n",
 			config->filename);
 		ast_config_destroy(cfg);
@@ -288,7 +317,7 @@
 			ast_log(LOG_NOTICE, "Retaining existing configuration for object of type '%s' with id '%s'\n", type, id);
 		}
 
-		ao2_link_flags(objects, obj, OBJ_NOLOCK);
+		ao2_link(objects, obj);
 	}
 
 	ao2_global_obj_replace_unref(config->objects, objects);
@@ -317,7 +346,6 @@
 	ast_uuid_generate_str(config->uuid, sizeof(config->uuid));
 
 	ast_rwlock_init(&config->objects.lock);
-	config->buckets = DEFAULT_OBJECT_BUCKETS;
 	strcpy(config->filename, filename);
 
 	while ((option = strsep(&tmp, ","))) {
@@ -325,8 +353,8 @@
 
 		if (!strcasecmp(name, "buckets")) {
 			if (sscanf(value, "%30u", &config->buckets) != 1) {
-				ast_log(LOG_ERROR, "Unsupported bucket size of '%s' used for configuration file '%s', defaulting to '%d'\n",
-					value, filename, DEFAULT_OBJECT_BUCKETS);
+				ast_log(LOG_ERROR, "Unsupported bucket size of '%s' used for configuration file '%s', defaulting to automatic determination\n",
+					value, filename);
 			}
 		} else if (!strcasecmp(name, "integrity")) {
 			if (!strcasecmp(value, "file")) {




More information about the svn-commits mailing list