Optimizations in the hash table module. (CVS 1896)

FossilOrigin-Name: d5b0269e0dd7c310460a7ffc4120ed45db823ce9
This commit is contained in:
drh 2004-08-20 14:08:50 +00:00
parent 7ac25c7510
commit e8cf2cacb1
4 changed files with 84 additions and 65 deletions

View File

@ -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

View File

@ -1 +1 @@
28215096e0748b5b02776ddb4c964e0161bc0f16
d5b0269e0dd7c310460a7ffc4120ed45db823ce9

View File

@ -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 <assert.h>
@ -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;
}

View File

@ -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_ */