[asterisk-commits] murf: branch murf/fast-ast2 r87261 - in /team/murf/fast-ast2: include/asteris...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Oct 27 18:00:37 CDT 2007


Author: murf
Date: Sat Oct 27 18:00:37 2007
New Revision: 87261

URL: http://svn.digium.com/view/asterisk?view=rev&rev=87261
Log:
OK, this is a working version of the code. But, my benchmarks show that for large db's, this version runs 16x or more faster, at small scale, this runs about half as fast as unmodified trunk. But, I have some optimizations I can implement... (oh, and by the way, trunk has slowed down about 21 percent since the last time I played with this stuff--- that's a significant slowdown.

Modified:
    team/murf/fast-ast2/include/asterisk/hashtab.h
    team/murf/fast-ast2/main/hashtab.c
    team/murf/fast-ast2/main/pbx.c

Modified: team/murf/fast-ast2/include/asterisk/hashtab.h
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast2/include/asterisk/hashtab.h?view=diff&rev=87261&r1=87260&r2=87261
==============================================================================
--- team/murf/fast-ast2/include/asterisk/hashtab.h (original)
+++ team/murf/fast-ast2/include/asterisk/hashtab.h Sat Oct 27 18:00:37 2007
@@ -190,7 +190,7 @@
 
     /* if you know the hash val for the object, then use this and avoid the recalc
 	   of the hash (the modulus (table_size) is not applied) */
-void * ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, int hashval);
+void * ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, unsigned int hashval);
 
 	/* same as the above lookup, but sets h to the key hash value if the lookup fails -- this has the modulus 
        applied, and will not be useful for long term storage if the table is resizable */

Modified: team/murf/fast-ast2/main/hashtab.c
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast2/main/hashtab.c?view=diff&rev=87261&r1=87260&r2=87261
==============================================================================
--- team/murf/fast-ast2/main/hashtab.c (original)
+++ team/murf/fast-ast2/main/hashtab.c Sat Oct 27 18:00:37 2007
@@ -381,21 +381,19 @@
 
 	/* will force a resize if the resize func returns 1 */
 	/* returns 1 on success, 0 if there's a problem */
-	int h;
+	unsigned int h;
 	int c;
 	struct ast_hashtab_bucket *b;
 	
 	if (!tab) {
-		ast_log(LOG_WARNING,"NULL table pointer given to INSERT.\n");
 		return 0;
 	}
 	if (!obj) {
-		ast_log(LOG_WARNING,"NULL object pointer given to INSERT.\n");
 		return 0;
 	}
 	if (tab->do_locking)
 		ast_rwlock_wrlock(&tab->lock);
-	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
+	h = ((unsigned int)((*tab->hash)(obj))) % tab->hash_tab_size;
 	for (c=0,b=tab->array[h];b;b=b->next) {
 		c++;
 	}
@@ -464,7 +462,11 @@
 
 	if (ast_hashtab_lookup_bucket(tab,obj,&bucket) == 0)
 	{
-		return ast_hashtab_insert_immediate_bucket(tab,obj,bucket);
+		int ret2 = ast_hashtab_insert_immediate_bucket(tab,obj,bucket);
+		if (tab->do_locking)
+			ast_rwlock_unlock(&tab->lock);
+		
+		return ret2;
 	}
 	if (tab->do_locking)
 		ast_rwlock_unlock(&tab->lock);
@@ -474,7 +476,7 @@
 void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
 {
 	/* lookup this object in the hash table. return a ptr if found, or NULL if not */
-	int h;
+	unsigned int h;
 	const void *ret;
 	struct ast_hashtab_bucket *b;
 	if (!tab || !obj)
@@ -482,7 +484,7 @@
 	
 	if (tab->do_locking)
 		ast_rwlock_rdlock(&tab->lock);
-	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
+	h = ((unsigned int)((*tab->hash)(obj))) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next) {
 		if ((*tab->compare)(obj,b->object) == 0) {
 			ret = b->object;
@@ -497,10 +499,10 @@
 	return 0;
 }
 
-void * ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, int hashval)
+void * ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, unsigned int hashval)
 {
 	/* lookup this object in the hash table. return a ptr if found, or NULL if not */
-	int h;
+	unsigned int h;
 	const void *ret;
 	struct ast_hashtab_bucket *b;
 	if (!tab || !obj)
@@ -526,16 +528,14 @@
 void * ast_hashtab_lookup_bucket(struct ast_hashtab *tab, const void *obj, int *bucket)
 {
 	/* lookup this object in the hash table. return a ptr if found, or NULL if not */
-	int h;
+	unsigned int h;
 	struct ast_hashtab_bucket *b;
 	if (!tab || !obj)
 		return 0;
 	
-	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
+	h = ((unsigned int)((*tab->hash)(obj))) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next) {
 		if ((*tab->compare)(obj,b->object) == 0) {
-			if (tab->do_locking)
-				ast_rwlock_unlock(&tab->lock);
 			return (void*)b->object; /* I can't touch obj in this func, but the outside world is welcome to */
 		}
 	}
@@ -578,7 +578,8 @@
 {
 	/* this function is called either internally, when the resize func returns 1, or
 	   externally by the user to force a resize of the hash table */
-	int newsize = (*tab->newsize)(tab), i, h,c;
+	int newsize = (*tab->newsize)(tab), i, c;
+	unsigned int h;
 	struct ast_hashtab_bucket *b,*bn;
 	
 	/* Since we keep a DLL of all the buckets in tlist,
@@ -601,7 +602,7 @@
 	{
 		b->prev = 0;
 		bn = b->tnext;
-		h = ((*tab->hash)(b->object)) % tab->hash_tab_size;
+		h = ((unsigned int)((*tab->hash)(b->object))) % tab->hash_tab_size;
 		b->next = tab->array[h];
 		if (b->next)
 			b->next->prev = b;
@@ -715,14 +716,14 @@
 void *ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj)
 {
 	/* looks up the object; removes the corresponding bucket */
-	int h;
+	unsigned int h;
 	struct ast_hashtab_bucket *b;
 
 	if (!tab || !obj)
 		return 0;
 	if (tab->do_locking)
 		ast_rwlock_wrlock(&tab->lock);
-	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
+	h = ((unsigned int)((*tab->hash)(obj))) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next)
 	{
 		void *obj2;
@@ -745,12 +746,12 @@
 void *ast_hashtab_remove_object_via_lookup_nolock(struct ast_hashtab *tab, void *obj)
 {
 	/* looks up the object; removes the corresponding bucket */
-	int h;
+	unsigned int h;
 	struct ast_hashtab_bucket *b;
 
 	if (!tab || !obj)
 		return 0;
-	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
+	h = ((unsigned int)((*tab->hash)(obj))) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next)
 	{
 		void *obj2;
@@ -773,7 +774,7 @@
 	/* looks up the object by hash and then comparing pts in bucket list instead of
 	   calling the compare routine; removes the bucket -- a slightly cheaper operation */
 	/* looks up the object; removes the corresponding bucket */
-	int h;
+	unsigned int h;
 	struct ast_hashtab_bucket *b;
 
 	if (!tab || !obj)
@@ -782,7 +783,7 @@
 	if (tab->do_locking)
 		ast_rwlock_wrlock(&tab->lock);
 
-	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
+	h = ((unsigned int)((*tab->hash)(obj))) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next)
 	{
 		const void *obj2;
@@ -808,13 +809,13 @@
 	/* looks up the object by hash and then comparing pts in bucket list instead of
 	   calling the compare routine; removes the bucket -- a slightly cheaper operation */
 	/* looks up the object; removes the corresponding bucket */
-	int h;
+	unsigned int h;
 	struct ast_hashtab_bucket *b;
 
 	if (!tab || !obj)
 		return 0;
  
-	h = ((*tab->hash)(obj)) % tab->hash_tab_size;
+	h = ((unsigned int)((*tab->hash)(obj))) % tab->hash_tab_size;
 	for (b=tab->array[h]; b; b=b->next)
 	{
 		const void *obj2;

Modified: team/murf/fast-ast2/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/murf/fast-ast2/main/pbx.c?view=diff&rev=87261&r1=87260&r2=87261
==============================================================================
--- team/murf/fast-ast2/main/pbx.c (original)
+++ team/murf/fast-ast2/main/pbx.c Sat Oct 27 18:00:37 2007
@@ -341,7 +341,7 @@
 	const struct ast_context *ac = ah_a;
 	const struct ast_context *bc = ah_b;
 	/* assume context names are registered in a string table! */
-	return ac->name != bc->name;
+	return strcmp(ac->name, bc->name);
 }
 
 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
@@ -362,7 +362,7 @@
 {
 	const struct ast_exten *ac = ah_a;
 	const struct ast_exten *bc = ah_b;
-	return ac->label != bc->label;
+	return strcmp(ac->label, bc->label);
 }
 
 static int hashtab_hash_contexts(const void *obj)
@@ -834,6 +834,19 @@
 	}
 }
 
+static void print_match_char_tree(struct match_char *node, char *prefix)
+{
+	char my_prefix[1024];
+	
+	ast_log(LOG_DEBUG,"%s%s:%c:%d:%s\n", prefix, node->x, node->is_pattern ? 'Y':'N', node->specificity, node->exten? "EXTEN":"");
+	strcpy(my_prefix,prefix);
+	strcat(my_prefix,"+-----------------");
+	if (node->next_char)
+		print_match_char_tree(node->next_char, my_prefix);
+	if (node->alt_char)
+		print_match_char_tree(node->alt_char, prefix);
+}
+
 struct ast_exten *get_canmatch_exten(struct match_char *node)
 {
 	/* find the exten at the end of the rope */
@@ -847,7 +860,7 @@
 void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid)
 {
 	struct match_char *p; /* note minimal stack storage requirements */
-
+	ast_log(LOG_DEBUG,"Looking for %s in match_char tree\n", str);
 	for (p=tree; p; p=p->alt_char)
 	{
 		if (p->x[0] == 'N' && p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
@@ -976,15 +989,21 @@
 {
 	struct ast_hashtab_iter *t1;
 	struct ast_exten *e1;
-	struct match_char *m1,*m2;
+	struct match_char *m1=0,*m2=0;
 	char buf[256];
 	int already;
 	int specif;
+	int biggest_bucket, resizes, numobjs, numbucks;
 	
+	ast_log(LOG_DEBUG,"Creating Extension Trie for context %s\n", con->name);
+	ast_hashtab_get_stats(con->root_tree, &biggest_bucket, &resizes, &numobjs, &numbucks);
+	ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
+			numobjs, numbucks, biggest_bucket, resizes);
 	t1 = ast_hashtab_start_traversal(con->root_tree);
 	while( (e1 = ast_hashtab_next(t1)) ) {
 		int pattern = 0;
 		char *s1 = e1->exten;
+		ast_log(LOG_DEBUG,"Adding exten %s to tree\n", s1);
 		m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
 		already = 1;
 
@@ -1044,6 +1063,7 @@
 		}
 		m1->exten =  e1; /* that last node should have an exten pointer */
 	}
+	ast_hashtab_end_traversal(t1);
 	return m1; /* just in case you want to see how the pattern ended */
 }
 
@@ -1338,9 +1358,9 @@
 
 struct fake_context /* this struct is purely for matching in the hashtab */
 {
-	ast_mutex_t lock; 			
+	ast_rwlock_t lock; 			
 	struct ast_exten *root;		
-	struct trb_table *root_tree;            
+	struct ast_hashtab *root_tree;            
 	struct match_char *pattern_tree;       
 	struct ast_context *next;	
 	struct ast_include *includes;		
@@ -1357,14 +1377,22 @@
 	struct fake_context item;
 	strncpy(item.name,name,256);
 	ast_rdlock_contexts();
-	if( contexts_tree )
+	if( contexts_tree ) {
 		tmp = ast_hashtab_lookup(contexts_tree,&item);
-#ifdef NOTNOW
-	while ( (tmp = ast_walk_contexts(tmp)) ) {
-		if (!name || !strcasecmp(name, tmp->name))
-			break;
-	}
-#endif
+		if (tmp)
+			ast_log(LOG_DEBUG,"Found context %s via HASH\n", tmp->name);
+		else
+			ast_log(LOG_DEBUG,"NOT Found context %s via HASH\n", name);
+    } else {
+		while ( (tmp = ast_walk_contexts(tmp)) ) {
+			if (!name || !strcasecmp(name, tmp->name))
+				break;
+		}
+		if (tmp)
+			ast_log(LOG_DEBUG,"Found context %s via LIST\n", tmp->name);
+		else
+			ast_log(LOG_DEBUG,"NOT Found context %s via LIST\n", name);
+	}
 	ast_unlock_contexts();
 	return tmp;
 }
@@ -1446,7 +1474,12 @@
 	score.exten = 0;
 	score.total_length = 0;
 	if (!tmp->pattern_tree)
+	{
 		create_match_char_tree(tmp);
+		ast_log(LOG_DEBUG,"Tree Created in context %s:\n", context);
+		print_match_char_tree(tmp->pattern_tree," ");
+	}
+	
 	new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid);
 	eroot = score.exten;
 
@@ -3302,6 +3335,11 @@
 	strncpy(item.name, context, 256);
 	ast_rdlock_contexts();
 	c = ast_hashtab_lookup(contexts_tree,&item);
+	if (c)
+		ast_log(LOG_DEBUG,"Found context %s\n", c->name);
+	else
+		ast_log(LOG_DEBUG,"NOT Found context %s\n", context);
+
 #ifdef NOTNOW
 
 	while ( (c = ast_walk_contexts(c)) ) {
@@ -4532,13 +4570,15 @@
 	struct fake_context search;
 	int length = sizeof(struct ast_context) + strlen(name) + 1;
 
-	if (!contexts_tree)
+	if (!contexts_tree) {
+		ast_log(LOG_DEBUG,"Creating Context Hash Table...\n");
 		contexts_tree = ast_hashtab_create(17,
 										   hashtab_compare_contexts, 
 										   ast_hashtab_resize_java,
 										   ast_hashtab_newsize_java,
 										   hashtab_hash_contexts,
 										   1);
+	}
 	strncpy(search.name,name,sizeof(search.name));
 	tmp = ast_hashtab_lookup(contexts_tree, &search);
 	
@@ -5580,7 +5620,7 @@
 		 * so insert in the main list right before 'e' (if any)
 		 */
 		tmp->next = e;
-		if (el) {
+		if (el) {  /* there is another exten already in this context */
 			el->next = tmp;
 			tmp->peer_tree = ast_hashtab_create(13,
 							hashtab_compare_exten_numbers,
@@ -5598,13 +5638,15 @@
 				ast_hashtab_insert_safe(tmp->peer_label_tree,tmp);
 			ast_hashtab_insert_safe(tmp->peer_tree, tmp);
 
-		} else {
-			con->root_tree = ast_hashtab_create(27,
-						hashtab_compare_extens,
-						ast_hashtab_resize_java,
-						ast_hashtab_newsize_java,
-						hashtab_hash_extens,
-						1);
+		} else {  /* this is the first exten in this context */
+			/* ast_log(LOG_DEBUG, "Creating Hash Tables for exten/priorities/labels for %s/%s\n", con->name, extension); */
+			if (!con->root_tree)
+				con->root_tree = ast_hashtab_create(27,
+													hashtab_compare_extens,
+													ast_hashtab_resize_java,
+													ast_hashtab_newsize_java,
+													hashtab_hash_extens,
+													1);
 			con->root = tmp;
 			con->root->peer_tree = ast_hashtab_create(13,
 								hashtab_compare_exten_numbers,
@@ -5623,6 +5665,7 @@
 			ast_hashtab_insert_safe(con->root->peer_tree, tmp);
 		}
 		ast_hashtab_insert_safe(con->root_tree, tmp);
+		ast_log(LOG_DEBUG,"Added %s to %s's root tree, tree=%x, els=%d", tmp->exten, con->name, (unsigned int)con->root_tree, ast_hashtab_size(con->root_tree));
 		ast_unlock_context(con);
 		if (tmp->priority == PRIORITY_HINT)
 			ast_add_hint(tmp);
@@ -7057,7 +7100,7 @@
 	while ( (inc = ast_walk_context_includes(con, inc)) )
 		if (!ast_context_find(inc->rname)) {
 			res = -1;
-			ast_log(LOG_WARNING, "Context '%s' tries includes nonexistent context '%s'\n",
+			ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
 					ast_get_context_name(con), inc->rname);
 		}
 	return res;




More information about the asterisk-commits mailing list