]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Automatically increase the size of the pager hash table as the number
authordrh <drh@noemail.net>
Sun, 7 May 2006 17:49:38 +0000 (17:49 +0000)
committerdrh <drh@noemail.net>
Sun, 7 May 2006 17:49:38 +0000 (17:49 +0000)
of in-memory pages increases.  Tickets #1790 and #1799. (CVS 3180)

FossilOrigin-Name: ef8e9886f40c8528604264308f5e4734ae6706c5

manifest
manifest.uuid
src/pager.c

index 62bf1968b78b3fb33151168ee06bfa63b469a21a..5bd8600746f352a928e059f939940eaa7d18a616 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\stypo\son\sa\swebpage.\s\sTicket\s#1792.\s(CVS\s3179)
-D 2006-05-03T23:39:37
+C Automatically\sincrease\sthe\ssize\sof\sthe\spager\shash\stable\sas\sthe\snumber\nof\sin-memory\spages\sincreases.\s\sTickets\s#1790\sand\s#1799.\s(CVS\s3180)
+D 2006-05-07T17:49:39
 F Makefile.in 5d8dff443383918b700e495de42ec65bc1c8865b
 F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -59,7 +59,7 @@ F src/os_unix.c 17d91581a0ab478a06cb6f257b707a4c4a93e5a7
 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
 F src/os_win.c 8ced9ac82670bbf77492961a2f7ff80a87f1404f
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 57348b21910450b47cdb7ab7a9a4e6bac68f6a5f
+F src/pager.c ddd05666bb89808a516baef2c186d6a75887ae90
 F src/pager.h 43f32f3847421f7502cfbb66f4eb2302b8033818
 F src/parse.y ee1887ce0e6eea15cc728913ad3462898f88e9b0
 F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55
@@ -355,7 +355,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 8f820e435272c0a4861421508c7e6f2979c2750f
-R 04653401c505e2c6061ff2b69b857755
+P 2702205277f45aadd2f07d51f71af4efd266228f
+R 682ba0f4fded90e799844395c2609fd0
 U drh
-Z 8508385ee7359f0e5208e0edf1f45b07
+Z 5c4f907a07f2808d253fc1ec4dae9689
index 4e9d3c0578c08a0f3379488dbd8eb54f3d1bf5b8..50e347c15fb5a48b3b0e3818ec9e960ec83442be 100644 (file)
@@ -1 +1 @@
-2702205277f45aadd2f07d51f71af4efd266228f
\ No newline at end of file
+ef8e9886f40c8528604264308f5e4734ae6706c5
\ No newline at end of file
index 4a438c0dc4131daac5fdfe44bc3d0a43101f4ad0..2e9982d710dacbe653c34e7a2cde87701936dc57 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.267 2006/05/03 23:34:06 drh Exp $
+** @(#) $Id: pager.c,v 1.268 2006/05/07 17:49:39 drh Exp $
 */
 #ifndef SQLITE_OMIT_DISKIO
 #include "sqliteInt.h"
@@ -208,24 +208,6 @@ struct PgHistory {
 #define PGHDR_TO_HIST(P,PGR)  \
             ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra])
 
-/*
-** How big to make the hash table used for locating in-memory pages
-** by page number. This macro looks a little silly, but is evaluated
-** at compile-time, not run-time (at least for gcc this is true).
-*/
-#define N_PG_HASH (\
-  (MAX_PAGES>1024)?2048: \
-  (MAX_PAGES>512)?1024: \
-  (MAX_PAGES>256)?512: \
-  (MAX_PAGES>128)?256: \
-  (MAX_PAGES>64)?128:64 \
-)
-
-/*
-** Hash a page number
-*/
-#define pager_hash(PN)  ((PN)&(N_PG_HASH-1))
-
 /*
 ** A open page cache is an instance of the following structure.
 **
@@ -296,7 +278,8 @@ struct Pager {
   void (*xReiniter)(void*,int);   /* Call this routine when reloading pages */
   void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
   void *pCodecArg;            /* First argument to xCodec() */
-  PgHdr *aHash[N_PG_HASH];    /* Hash table to map page number to PgHdr */
+  int nHash;                  /* Size of the pager hash table */
+  PgHdr **aHash;              /* Hash table to map page number to PgHdr */
 #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   Pager *pNext;               /* Linked list of pagers in this thread */
 #endif
@@ -403,6 +386,33 @@ static const unsigned char aJournalMagic[] = {
 # define REFINFO(X)
 #endif
 
+
+/*
+** Change the size of the pager hash table to N.  N must be a power
+** of two.
+*/
+static void pager_resize_hash_table(Pager *pPager, int N){
+  PgHdr **aHash, *pPg;
+  assert( N>0 && (N&(N-1))==0 );
+  aHash = sqliteMalloc( sizeof(aHash[0])*N );
+  if( aHash==0 ){
+    /* Failure to rehash is not an error.  It is only a performance hit. */
+    return;
+  }
+  sqliteFree(pPager->aHash);
+  pPager->nHash = N;
+  pPager->aHash = aHash;
+  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+    int h = pPg->pgno & (N-1);
+    pPg->pNextHash = aHash[h];
+    if( aHash[h] ){
+      aHash[h]->pPrevHash = pPg;
+    }
+    aHash[h] = pPg;
+    pPg->pPrevHash = 0;
+  }
+}
+
 /*
 ** Read a 32-bit integer from the given file descriptor.  Store the integer
 ** that is read in *pRes.  Return SQLITE_OK if everything worked, or an
@@ -822,7 +832,9 @@ static void page_remove_from_stmt_list(PgHdr *pPg){
 ** a pointer to the page or NULL if not found.
 */
 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
-  PgHdr *p = pPager->aHash[pager_hash(pgno)];
+  PgHdr *p;
+  if( pPager->aHash==0 ) return 0;
+  p = pPager->aHash[pgno & (pPager->nHash-1)];
   while( p && p->pgno!=pgno ){
     p = p->pNextHash;
   }
@@ -846,8 +858,10 @@ static void pager_reset(Pager *pPager){
   pPager->pFirstSynced = 0;
   pPager->pLast = 0;
   pPager->pAll = 0;
-  memset(pPager->aHash, 0, sizeof(pPager->aHash));
+  pPager->nHash = 0;
+  sqliteFree(pPager->aHash);
   pPager->nPage = 0;
+  pPager->aHash = 0;
   if( pPager->state>=PAGER_RESERVED ){
     sqlite3pager_rollback(pPager);
   }
@@ -1849,10 +1863,10 @@ static void unlinkHashChain(Pager *pPager, PgHdr *pPg){
     pPg->pNextHash->pPrevHash = pPg->pPrevHash;
   }
   if( pPg->pPrevHash ){
-    assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg );
+    assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg );
     pPg->pPrevHash->pNextHash = pPg->pNextHash;
   }else{
-    int h = pager_hash(pPg->pgno);
+    int h = pPg->pgno & (pPager->nHash-1);
     assert( pPager->aHash[h]==pPg );
     pPager->aHash[h] = pPg->pNextHash;
   }
@@ -2084,7 +2098,7 @@ int sqlite3pager_close(Pager *pPager){
     pTmp->pNext = pPager->pNext;
   }
 #endif
-
+  sqliteFree(pPager->aHash);
   sqliteFree(pPager);
   return SQLITE_OK;
 }
@@ -2622,6 +2636,13 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
     TEST_INCR(pPager->nMiss);
     if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ){
       /* Create a new page */
+      if( pPager->nPage>=pPager->nHash ){
+        pager_resize_hash_table(pPager,
+           pPager->nHash<256 ? 256 : pPager->nHash*2);
+        if( pPager->nHash==0 ){
+          return SQLITE_NOMEM;
+        }
+      }
       pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize
                               + sizeof(u32) + pPager->nExtra
                               + MEMDB*sizeof(PgHistory) );
@@ -2710,7 +2731,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
     }
 
     /* Link the page into the page hash table */
-    h = pager_hash(pgno);
+    h = pgno & (pPager->nHash-1);
     pPg->pNextHash = pPager->aHash[h];
     pPager->aHash[h] = pPg;
     if( pPg->pNextHash ){
@@ -3766,7 +3787,7 @@ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){
 
   /* Change the page number for pPg and insert it into the new hash-chain. */
   pPg->pgno = pgno;
-  h = pager_hash(pgno);
+  h = pgno & (pPager->nHash-1);
   if( pPager->aHash[h] ){
     assert( pPager->aHash[h]->pPrevHash==0 );
     pPager->aHash[h]->pPrevHash = pPg;