]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Optimizations in the hash table module. (CVS 1896)
authordrh <drh@noemail.net>
Fri, 20 Aug 2004 14:08:50 +0000 (14:08 +0000)
committerdrh <drh@noemail.net>
Fri, 20 Aug 2004 14:08:50 +0000 (14:08 +0000)
FossilOrigin-Name: d5b0269e0dd7c310460a7ffc4120ed45db823ce9

manifest
manifest.uuid
src/hash.c
src/hash.h

index 7612978423a1e123b49bf7e1e4eb0ec4d64db460..d84f25aa95d3993124f9e75fed7e49df7221afc1 100644 (file)
--- 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
index bf9293ab4d082fc568ba9283270cabfd3cba2f34..7145bd5ef1e40596d882c2a08db9c91bbf6d4835 100644 (file)
@@ -1 +1 @@
-28215096e0748b5b02776ddb4c964e0161bc0f16
\ No newline at end of file
+d5b0269e0dd7c310460a7ffc4120ed45db823ce9
\ No newline at end of file
index 3ee23dd9db4dd8c9beec63dc77ac326bedc36068..847d06bbec9633c7ccaf2ae7d297a9ff1912bcb1 100644 (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>
 */
 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;
 }
index 4586501440f1ae24726cd7a2933d7f6984d97ff9..aa17828a6e4ace2e536368092882f29e93248701 100644 (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_ */
-
-
-