From: drh Date: Fri, 20 Aug 2004 14:08:50 +0000 (+0000) Subject: Optimizations in the hash table module. (CVS 1896) X-Git-Tag: version-3.6.10~4249 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e8cf2cacb1f553f8245a5dd08349be2c02373dc2;p=thirdparty%2Fsqlite.git Optimizations in the hash table module. (CVS 1896) FossilOrigin-Name: d5b0269e0dd7c310460a7ffc4120ed45db823ce9 --- diff --git a/manifest b/manifest index 7612978423..d84f25aa95 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\slemon\sso\sthat\sa\s@X\sinstead\sof\sjust\sX\sin\sthe\scode\sexpands\sto\sthe\nmajor\stoken\svalue\srather\sthan\sthe\sminor\stoken\svalue.\s\sUse\sthis\sto\smake\nthe\sparser\sa\sfew\shundred\sbytes\ssmaller.\s(CVS\s1895) -D 2004-08-19T15:12:26 +C Optimizations\sin\sthe\shash\stable\smodule.\s(CVS\s1896) +D 2004-08-20T14:08:51 F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -35,8 +35,8 @@ F src/delete.c e81545e546f6bc87d7508a93a09ca70695265af3 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 F src/expr.c f11a1e5c489bc8f5cc83b10aa80f21e85f48141e F src/func.c 7e2eeebe219aa612ce7a04c74ae6d57379c6656b -F src/hash.c f0a2f22c2a7052d67053b5f4690ea3010bb3fb9f -F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb +F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 +F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/insert.c bedcba371401395033a1a1c578d8fdc3fec87bec F src/legacy.c 2f3617c61bcdcd1d776154a9cfebf99facda8ad8 F src/main.c a779422c5402df92c390e233ac32ab718fc4436b @@ -243,7 +243,7 @@ F www/tclsqlite.tcl 06a86cba4d7fc88e2bcd633b57702d3d16abebb5 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 25fe7a42ec2e06e659d7a0a6664789114c007e17 -R 0379dd9278368974892dd5434039fab5 +P 28215096e0748b5b02776ddb4c964e0161bc0f16 +R 5607576f6316ac80134bcd33d2f77b9e U drh -Z ddb5c020240eaf2ea91499a31fc16aa6 +Z d2ae7348c29545bbd90048ea25e77c25 diff --git a/manifest.uuid b/manifest.uuid index bf9293ab4d..7145bd5ef1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -28215096e0748b5b02776ddb4c964e0161bc0f16 \ No newline at end of file +d5b0269e0dd7c310460a7ffc4120ed45db823ce9 \ No newline at end of file diff --git a/src/hash.c b/src/hash.c index 3ee23dd9db..847d06bbec 100644 --- a/src/hash.c +++ b/src/hash.c @@ -12,7 +12,7 @@ ** This is the implementation of generic hash-tables ** used in SQLite. ** -** $Id: hash.c,v 1.14 2004/06/30 22:43:22 drh Exp $ +** $Id: hash.c,v 1.15 2004/08/20 14:08:51 drh Exp $ */ #include "sqliteInt.h" #include @@ -31,10 +31,12 @@ */ void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){ assert( pNew!=0 ); - assert( keyClass>=SQLITE_HASH_INT && keyClass<=SQLITE_HASH_BINARY ); + assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY ); pNew->keyClass = keyClass; - pNew->copyKey = copyKey && - (keyClass==SQLITE_HASH_STRING || keyClass==SQLITE_HASH_BINARY); +#if 0 + if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0; +#endif + pNew->copyKey = copyKey; pNew->first = 0; pNew->count = 0; pNew->htsize = 0; @@ -99,7 +101,7 @@ static int strHash(const void *pKey, int nKey){ return sqlite3HashNoCase((const char*)pKey, nKey); } static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return n2-n1; + if( n1!=n2 ) return 1; return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1); } @@ -115,7 +117,7 @@ static int binHash(const void *pKey, int nKey){ return h & 0x7fffffff; } static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){ - if( n1!=n2 ) return n2-n1; + if( n1!=n2 ) return 1; return memcmp(pKey1,pKey2,n1); } @@ -132,14 +134,23 @@ static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){ ** with types "const void*" and "int" and returns an "int". */ static int (*hashFunction(int keyClass))(const void*,int){ +#if 0 /* HASH_INT and HASH_POINTER are never used */ switch( keyClass ){ - /* case SQLITE_HASH_INT: return &intHash; // NOT USED */ - /* case SQLITE_HASH_POINTER: return &ptrHash; // NOT USED */ + case SQLITE_HASH_INT: return &intHash; + case SQLITE_HASH_POINTER: return &ptrHash; case SQLITE_HASH_STRING: return &strHash; case SQLITE_HASH_BINARY: return &binHash;; default: break; } return 0; +#else + if( keyClass==SQLITE_HASH_STRING ){ + return &strHash; + }else{ + assert( keyClass==SQLITE_HASH_BINARY ); + return &binHash; + } +#endif } /* @@ -149,14 +160,48 @@ static int (*hashFunction(int keyClass))(const void*,int){ ** see the header comment on the previous function. */ static int (*compareFunction(int keyClass))(const void*,int,const void*,int){ +#if 0 /* HASH_INT and HASH_POINTER are never used */ switch( keyClass ){ - /* case SQLITE_HASH_INT: return &intCompare; // NOT USED */ - /* case SQLITE_HASH_POINTER: return &ptrCompare; // NOT USED */ + case SQLITE_HASH_INT: return &intCompare; + case SQLITE_HASH_POINTER: return &ptrCompare; case SQLITE_HASH_STRING: return &strCompare; case SQLITE_HASH_BINARY: return &binCompare; default: break; } return 0; +#else + if( keyClass==SQLITE_HASH_STRING ){ + return &strCompare; + }else{ + assert( keyClass==SQLITE_HASH_BINARY ); + return &binCompare; + } +#endif +} + +/* Link an element into the hash table +*/ +static void insertElement( + Hash *pH, /* The complete hash table */ + struct _ht *pEntry, /* The entry into which pNew is inserted */ + HashElem *pNew /* The element to be inserted */ +){ + HashElem *pHead; /* First element already in pEntry */ + pHead = pEntry->chain; + if( pHead ){ + pNew->next = pHead; + pNew->prev = pHead->prev; + if( pHead->prev ){ pHead->prev->next = pNew; } + else { pH->first = pNew; } + pHead->prev = pNew; + }else{ + pNew->next = pH->first; + if( pH->first ){ pH->first->prev = pNew; } + pNew->prev = 0; + pH->first = pNew; + } + pEntry->count++; + pEntry->chain = pNew; } @@ -167,7 +212,6 @@ static int (*compareFunction(int keyClass))(const void*,int,const void*,int){ static void rehash(Hash *pH, int new_size){ struct _ht *new_ht; /* The new hash table */ HashElem *elem, *next_elem; /* For looping over existing elements */ - HashElem *x; /* Element being copied to new hash table */ int (*xHash)(const void*,int); /* The hash function */ assert( (new_size & (new_size-1))==0 ); @@ -180,21 +224,7 @@ static void rehash(Hash *pH, int new_size){ for(elem=pH->first, pH->first=0; elem; elem = next_elem){ int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); next_elem = elem->next; - x = new_ht[h].chain; - if( x ){ - elem->next = x; - elem->prev = x->prev; - if( x->prev ) x->prev->next = elem; - else pH->first = elem; - x->prev = elem; - }else{ - elem->next = pH->first; - if( pH->first ) pH->first->prev = elem; - elem->prev = 0; - pH->first = elem; - } - new_ht[h].chain = elem; - new_ht[h].count++; + insertElement(pH, &new_ht[h], elem); } } @@ -213,8 +243,9 @@ static HashElem *findElementGivenHash( int (*xCompare)(const void*,int,const void*,int); /* comparison function */ if( pH->ht ){ - elem = pH->ht[h].chain; - count = pH->ht[h].count; + struct _ht *pEntry = &pH->ht[h]; + elem = pEntry->chain; + count = pEntry->count; xCompare = compareFunction(pH->keyClass); while( count-- && elem ){ if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ @@ -234,6 +265,7 @@ static void removeElementGivenHash( HashElem* elem, /* The element to be removed from the pH */ int h /* Hash value for the element */ ){ + struct _ht *pEntry; if( elem->prev ){ elem->prev->next = elem->next; }else{ @@ -242,12 +274,13 @@ static void removeElementGivenHash( if( elem->next ){ elem->next->prev = elem->prev; } - if( pH->ht[h].chain==elem ){ - pH->ht[h].chain = elem->next; + pEntry = &pH->ht[h]; + if( pEntry->chain==elem ){ + pEntry->chain = elem->next; } - pH->ht[h].count--; - if( pH->ht[h].count<=0 ){ - pH->ht[h].chain = 0; + pEntry->count--; + if( pEntry->count<=0 ){ + pEntry->chain = 0; } if( pH->copyKey && elem->pKey ){ sqliteFree(elem->pKey); @@ -327,32 +360,21 @@ void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){ } new_elem->nKey = nKey; pH->count++; - if( pH->htsize==0 ) rehash(pH,8); if( pH->htsize==0 ){ - pH->count = 0; - sqliteFree(new_elem); - return data; + rehash(pH,8); + if( pH->htsize==0 ){ + pH->count = 0; + sqliteFree(new_elem); + return data; + } } if( pH->count > pH->htsize ){ rehash(pH,pH->htsize*2); } + assert( pH->htsize>0 ); assert( (pH->htsize & (pH->htsize-1))==0 ); h = hraw & (pH->htsize-1); - elem = pH->ht[h].chain; - if( elem ){ - new_elem->next = elem; - new_elem->prev = elem->prev; - if( elem->prev ){ elem->prev->next = new_elem; } - else { pH->first = new_elem; } - elem->prev = new_elem; - }else{ - new_elem->next = pH->first; - new_elem->prev = 0; - if( pH->first ){ pH->first->prev = new_elem; } - pH->first = new_elem; - } - pH->ht[h].count++; - pH->ht[h].chain = new_elem; + insertElement(pH, &pH->ht[h], new_elem); new_elem->data = data; return 0; } diff --git a/src/hash.h b/src/hash.h index 4586501440..aa17828a6e 100644 --- a/src/hash.h +++ b/src/hash.h @@ -12,7 +12,7 @@ ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** -** $Id: hash.h,v 1.7 2004/05/08 08:23:25 danielk1977 Exp $ +** $Id: hash.h,v 1.8 2004/08/20 14:08:51 drh Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ @@ -70,7 +70,7 @@ struct HashElem { ** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY ** if the copyKey parameter to HashInit is 1. */ -#define SQLITE_HASH_INT 1 +/* #define SQLITE_HASH_INT 1 // NOT USED */ /* #define SQLITE_HASH_POINTER 2 // NOT USED */ #define SQLITE_HASH_STRING 3 #define SQLITE_HASH_BINARY 4 @@ -107,6 +107,3 @@ void sqlite3HashClear(Hash*); #define sqliteHashCount(H) ((H)->count) #endif /* _SQLITE_HASH_H_ */ - - -