mirror of https://github.com/sqlite/sqlite
Optimizations in the hash table module. (CVS 1896)
FossilOrigin-Name: d5b0269e0dd7c310460a7ffc4120ed45db823ce9
This commit is contained in:
parent
7ac25c7510
commit
e8cf2cacb1
14
manifest
14
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
|
||||
|
|
|
@ -1 +1 @@
|
|||
28215096e0748b5b02776ddb4c964e0161bc0f16
|
||||
d5b0269e0dd7c310460a7ffc4120ed45db823ce9
|
126
src/hash.c
126
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 <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;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue