/* Simple speed tests using original critbit code (modified not to allocate). * * Results on my 32 bit Intel(R) Core(TM) i5 CPU M 560 @ 2.67GHz, gcc 4.5.2: * Run 100 times: Min-Max(Avg) #01: Initial insert: 237-257(239) #02: Initial lookup (match): 180-197(181) #03: Initial lookup (miss): 171-190(172) #04: Initial lookup (random): 441-455(446) #05: Initial delete all: 127-148(128) #06: Initial re-inserting: 219-298(221) #07: Deleting first half: 101-109(102) #08: Adding (a different) half: 159-165(160) #09: Lookup after half-change (match): 203-216(204) #10: Lookup after half-change (miss): 217-225(218) #11: Churn 1: 298-311(300) #12: Churn 2: 298-318(301) #13: Churn 3: 301-322(304) #14: Post-Churn lookup (match): 189-196(190) #15: Post-Churn lookup (miss): 189-197(191) #16: Post-Churn lookup (random): 500-531(506) */ #include #include #include #include #include #include #include #include #include #include /* CRITBIT source */ typedef struct { void *root; } critbit0_tree; int critbit0_contains(critbit0_tree *t, const char *u); int critbit0_insert(critbit0_tree *t, const char *u); int critbit0_delete(critbit0_tree *t, const char *u); void critbit0_clear(critbit0_tree *t); int critbit0_allprefixed(critbit0_tree *t, const char *prefix, int (*handle) (const char *, void *), void *arg); #define uint8 uint8_t #define uint32 uint32_t static size_t allocated; /*2:*/ #include #include #include #include #include typedef struct{ void*child[2]; uint32 byte; uint8 otherbits; }critbit0_node; /*:2*//*3:*/ int critbit0_contains(critbit0_tree*t,const char*u){ const uint8*ubytes= (void*)u; const size_t ulen= strlen(u); uint8*p= t->root; /*4:*/ if(!p)return 0; /*:4*/ /*5:*/ while(1&(intptr_t)p){ critbit0_node*q= (void*)(p-1); /*6:*/ uint8 c= 0; if(q->bytebyte]; const int direction= (1+(q->otherbits|c))>>8; /*:6*/ p= q->child[direction]; } /*:5*/ /*7:*/ return 0==strcmp(u,(const char*)p); /*:7*/ } /*:3*//*8:*/ int critbit0_insert(critbit0_tree*t,const char*u) { const uint8*const ubytes= (void*)u; const size_t ulen= strlen(u); uint8*p= t->root; /*9:*/ if(!p){ #if 0 char*x; int a= posix_memalign((void**)&x,sizeof(void*),ulen+1); if(a)return 0; memcpy(x,u,ulen+1); t->root= x; #else t->root = (char *)u; #endif return 2; } /*:9*/ /*5:*/ while(1&(intptr_t)p){ critbit0_node*q= (void*)(p-1); /*6:*/ uint8 c= 0; if(q->bytebyte]; const int direction= (1+(q->otherbits|c))>>8; /*:6*/ p= q->child[direction]; } /*:5*/ /*10:*/ /*11:*/ uint32 newbyte; uint32 newotherbits; for(newbyte= 0;newbyte>8; /*:12*/ /*:10*/ /*13:*/ /*14:*/ critbit0_node*newnode; if(posix_memalign((void**)&newnode,sizeof(void*),sizeof(critbit0_node)))return 0; allocated++; char*x; #if 0 if(posix_memalign((void**)&x,sizeof(void*),ulen+1)){ free(newnode); return 0; } memcpy(x,ubytes,ulen+1); #else x = (char *)u; #endif newnode->byte= newbyte; newnode->otherbits= newotherbits; newnode->child[1-newdirection]= x; /*:14*/ /*15:*/ void**wherep= &t->root; for(;;){ uint8*p= *wherep; if(!(1&(intptr_t)p))break; critbit0_node*q= (void*)(p-1); if(q->byte> newbyte)break; if(q->byte==newbyte&&q->otherbits> newotherbits)break; uint8 c= 0; if(q->bytebyte]; const int direction= (1+(q->otherbits|c))>>8; wherep= q->child+direction; } newnode->child[newdirection]= *wherep; *wherep= (void*)(1+(char*)newnode); /*:15*/ /*:13*/ return 2; } /*:8*//*16:*/ int critbit0_delete(critbit0_tree*t,const char*u){ const uint8*ubytes= (void*)u; const size_t ulen= strlen(u); uint8*p= t->root; void**wherep= &t->root; void**whereq= 0; critbit0_node*q= 0; int direction= 0; /*17:*/ if(!p)return 0; /*:17*/ /*18:*/ while(1&(intptr_t)p){ whereq= wherep; q= (void*)(p-1); uint8 c= 0; if(q->bytebyte]; direction= (1+(q->otherbits|c))>>8; wherep= q->child+direction; p= *wherep; } /*:18*/ /*19:*/ if(0!=strcmp(u,(const char*)p))return 0; #if 0 free(p); #endif /*:19*/ /*20:*/ if(!whereq){ t->root= 0; return 1; } *whereq= q->child[1-direction]; free(q); allocated--; /*:20*/ return 1; } /*:16*//*21:*/ static void traverse(void*top){ /*22:*/ uint8*p= top; if(1&(intptr_t)p){ critbit0_node*q= (void*)(p-1); traverse(q->child[0]); traverse(q->child[1]); free(q); allocated--; }else{ #if 0 free(p); #endif } /*:22*/ } void critbit0_clear(critbit0_tree*t) { if(t->root)traverse(t->root); t->root= NULL; } /*:21*//*23:*/ static int allprefixed_traverse(uint8*top, int(*handle)(const char*,void*),void*arg){ /*26:*/ if(1&(intptr_t)top){ critbit0_node*q= (void*)(top-1); int direction; for(direction= 0;direction<2;++direction) switch(allprefixed_traverse(q->child[direction],handle,arg)){ case 1:break; case 0:return 0; default:return-1; } return 1; } /*:26*/ /*27:*/ return handle((const char*)top,arg);/*:27*/ } int critbit0_allprefixed(critbit0_tree*t,const char*prefix, int(*handle)(const char*,void*),void*arg){ const uint8*ubytes= (void*)prefix; const size_t ulen= strlen(prefix); uint8*p= t->root; uint8*top= p; size_t i; if(!p)return 1; /*24:*/ while(1&(intptr_t)p){ critbit0_node*q= (void*)(p-1); uint8 c= 0; if(q->bytebyte]; const int direction= (1+(q->otherbits|c))>>8; p= q->child[direction]; if(q->byte