From: drh Date: Sun, 7 May 2006 17:49:38 +0000 (+0000) Subject: Automatically increase the size of the pager hash table as the number X-Git-Tag: version-3.6.10~2987 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8ca0c724b5085554b257d1e781eab389bb1f3a60;p=thirdparty%2Fsqlite.git Automatically increase the size of the pager hash table as the number of in-memory pages increases. Tickets #1790 and #1799. (CVS 3180) FossilOrigin-Name: ef8e9886f40c8528604264308f5e4734ae6706c5 --- diff --git a/manifest b/manifest index 62bf1968b7..5bd8600746 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 4e9d3c0578..50e347c15f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2702205277f45aadd2f07d51f71af4efd266228f \ No newline at end of file +ef8e9886f40c8528604264308f5e4734ae6706c5 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 4a438c0dc4..2e9982d710 100644 --- a/src/pager.c +++ b/src/pager.c @@ -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->nPagemxPage || 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;