1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

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
This commit is contained in:
drh
2006-05-07 17:49:38 +00:00
parent a28ca908e3
commit 8ca0c724b5
3 changed files with 55 additions and 34 deletions

View 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;