-C Change\sthe\spcache\smodule\sto\skeep\strack\sof\sthe\stotal\snumber\sof\sreferences\sto\nall\spages\srather\sthan\sthe\snumber\sof\spages\sreferences,\sfor\sa\sperformance\nimprovement\sand\ssize\sreduction.
-D 2015-09-03T20:43:55.204
+C Simplification\sof\sthe\sLRU\slist\shandling\sin\spcache1.
+D 2015-09-04T04:31:56.886
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in f85066ce844a28b671aaeeff320921cd0ce36239
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
-F src/pcache1.c e1529369c047ac645e6a28196f25b7e936c46b82
+F src/pcache1.c bf2afe64a3dedb8643c8dcbd94a145cc80ab2a67
F src/pragma.c d71b813e67bf03f3116b9dd5164fbfd81ec673a2
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 618d8dd4ff44cce10cc4688a2134715ff66cc562
-R 7304361de7c7fa82f683343fecc699dd
+P f00a9e1e998c4bd249a45444dc2d71a7e4903b8b
+R 231caff1c142ba151d728fb853afd78c
U drh
-Z 8da3824804c6c5593515c7564fca1c5b
+Z ce45274979109dc4b492f06dc4bc7386
typedef struct PgFreeslot PgFreeslot;
typedef struct PGroup PGroup;
+/*
+** Each cache entry is represented by an instance of the following
+** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
+** PgHdr1.pCache->szPage bytes is allocated directly before this structure
+** in memory.
+*/
+struct PgHdr1 {
+ sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
+ unsigned int iKey; /* Key value (page number) */
+ u8 isPinned; /* Page in use, not on the LRU list */
+ u8 isBulkLocal; /* This page from bulk local storage */
+ u8 isAnchor; /* This is the PGroup.lru element */
+ PgHdr1 *pNext; /* Next in hash table chain */
+ PCache1 *pCache; /* Cache that currently owns this page */
+ PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
+ PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
+};
+
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each other's unpinned
** pages when they are under memory pressure. A PGroup is an instance of
unsigned int nMinPage; /* Sum of nMin for purgeable caches */
unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
unsigned int nCurrentPage; /* Number of purgeable pages allocated */
- PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
+ PgHdr1 lru; /* The beginning and end of the LRU list */
};
/* Each page cache is an instance of the following object. Every
void *pBulk; /* Bulk memory used by pcache-local */
};
-/*
-** Each cache entry is represented by an instance of the following
-** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
-** PgHdr1.pCache->szPage bytes is allocated directly before this structure
-** in memory.
-*/
-struct PgHdr1 {
- sqlite3_pcache_page page;
- unsigned int iKey; /* Key value (page number) */
- u8 isPinned; /* Page in use, not on the LRU list */
- u8 isBulkLocal; /* This page from bulk local storage */
- PgHdr1 *pNext; /* Next in hash table chain */
- PCache1 *pCache; /* Cache that currently owns this page */
- PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
- PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
-};
-
/*
** Free slots in the allocator used to divide up the global page cache
** buffer provided using the SQLITE_CONFIG_PAGECACHE mechanism.
/******************************************************************************/
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
+
/*
** This function is called during initialization if a static buffer is
** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
pX->page.pBuf = zBulk;
pX->page.pExtra = &pX[1];
pX->isBulkLocal = 1;
+ pX->isAnchor = 0;
pX->pNext = pCache->pFree;
pCache->pFree = pX;
zBulk += pCache->szAlloc;
p->page.pBuf = pPg;
p->page.pExtra = &p[1];
p->isBulkLocal = 0;
+ p->isAnchor = 0;
}
if( pCache->bPurgeable ){
pCache->pGroup->nCurrentPage++;
assert( pPage!=0 );
assert( pPage->isPinned==0 );
pCache = pPage->pCache;
- assert( pPage->pLruNext || pPage==pCache->pGroup->pLruTail );
- assert( pPage->pLruPrev || pPage==pCache->pGroup->pLruHead );
+ assert( pPage->pLruNext );
+ assert( pPage->pLruPrev );
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
- if( pPage->pLruPrev ){
- pPage->pLruPrev->pLruNext = pPage->pLruNext;
- }else{
- pCache->pGroup->pLruHead = pPage->pLruNext;
- }
- if( pPage->pLruNext ){
- pPage->pLruNext->pLruPrev = pPage->pLruPrev;
- }else{
- pCache->pGroup->pLruTail = pPage->pLruPrev;
- }
+ pPage->pLruPrev->pLruNext = pPage->pLruNext;
+ pPage->pLruNext->pLruPrev = pPage->pLruPrev;
pPage->pLruNext = 0;
pPage->pLruPrev = 0;
pPage->isPinned = 1;
+ assert( pPage->isAnchor==0 );
+ assert( pCache->pGroup->lru.isAnchor==1 );
pCache->nRecyclable--;
return pPage;
}
*/
static void pcache1EnforceMaxPage(PCache1 *pCache){
PGroup *pGroup = pCache->pGroup;
+ PgHdr1 *p;
assert( sqlite3_mutex_held(pGroup->mutex) );
- while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
- PgHdr1 *p = pGroup->pLruTail;
+ while( pGroup->nCurrentPage>pGroup->nMaxPage
+ && (p=pGroup->lru.pLruPrev)->isAnchor==0
+ ){
assert( p->pCache->pGroup==pGroup );
assert( p->isPinned==0 );
pcache1PinPage(p);
}else{
pGroup = &pcache1.grp;
}
+ if( pGroup->lru.isAnchor==0 ){
+ pGroup->lru.isAnchor = 1;
+ pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru;
+ }
pCache->pGroup = pGroup;
pCache->szPage = szPage;
pCache->szExtra = szExtra;
/* Step 4. Try to recycle a page. */
if( pCache->bPurgeable
- && pGroup->pLruTail
+ && !pGroup->lru.pLruPrev->isAnchor
&& ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache))
){
PCache1 *pOther;
- pPage = pGroup->pLruTail;
+ pPage = pGroup->lru.pLruPrev;
assert( pPage->isPinned==0 );
pcache1RemoveFromHash(pPage, 0);
pcache1PinPage(pPage);
** part of the PGroup LRU list.
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
- assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
assert( pPage->isPinned==1 );
if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
pcache1RemoveFromHash(pPage, 1);
}else{
/* Add the page to the PGroup LRU list. */
- if( pGroup->pLruHead ){
- pGroup->pLruHead->pLruPrev = pPage;
- pPage->pLruNext = pGroup->pLruHead;
- pGroup->pLruHead = pPage;
- }else{
- pGroup->pLruTail = pPage;
- pGroup->pLruHead = pPage;
- }
+ PgHdr1 **ppFirst = &pGroup->lru.pLruNext;
+ pPage->pLruPrev = &pGroup->lru;
+ (pPage->pLruNext = *ppFirst)->pLruPrev = pPage;
+ *ppFirst = pPage;
pCache->nRecyclable++;
pPage->isPinned = 0;
}
if( sqlite3GlobalConfig.nPage==0 ){
PgHdr1 *p;
pcache1EnterMutex(&pcache1.grp);
- while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
+ while( (nReq<0 || nFree<nReq)
+ && (p=pcache1.grp.lru.pLruPrev)->isAnchor==0
+ ){
nFree += pcache1MemSize(p->page.pBuf);
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
nFree += sqlite3MemSize(p);
){
PgHdr1 *p;
int nRecyclable = 0;
- for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
+ for(p=pcache1.grp.lru.pLruNext; !p->isAnchor; p=p->pLruNext){
assert( p->isPinned==0 );
nRecyclable++;
}