Enhance the pcache1 page cache so that it tries to allocate a block of
SQLITE_DEFAULT_PCACHE_INITSZ pages from malloc() on startup, and uses those preallocated pages when possible rather than going to malloc() for each individual page. About a 5% performance increase for some workloads. FossilOrigin-Name: 5348ffc3fda5168c1e9e14aa88b0c6aedbda7c94
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
C Early\sdetection\sof\sfile\scorruption\sin\sa\sdebugging\sroutine,\sbefore\sthe\sinvalid\ndata\scan\scause\sproblems.
|
||||
D 2015-07-08T12:25:38.106
|
||||
C Enhance\sthe\spcache1\spage\scache\sso\sthat\sit\stries\sto\sallocate\sa\sblock\sof\nSQLITE_DEFAULT_PCACHE_INITSZ\spages\sfrom\smalloc()\son\sstartup,\sand\suses\sthose\npreallocated\spages\swhen\spossible\srather\sthan\sgoing\sto\smalloc()\sfor\seach\nindividual\spage.\s\sAbout\sa\s5%\sperformance\sincrease\sfor\ssome\sworkloads.
|
||||
D 2015-07-08T16:22:42.453
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 017bf0511d1b2dd1db5e16488fbf75a17b526cbc
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -269,7 +269,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c 4d9134dc988a87838c06056c89c0e8c4700a0452
|
||||
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 740ab30df845f4a2c2bdb731ed191b4b63b2b2eb
|
||||
F src/btree.c 781deff0d5af639e8dd4f83ec963cc3bbf8cffc2
|
||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||
F src/btreeInt.h 2ad754dd4528baa8d0946a593cc373b890bf859e
|
||||
F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
|
||||
@@ -283,7 +283,7 @@ F src/expr.c c5c58e4d01c7ceb2266791d8d877f1b23a88e316
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
|
||||
F src/func.c a98ea5880dc50e9ca6dd6f57079a37b9cfcdecf1
|
||||
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
|
||||
F src/global.c 508e4087f7b41d688e4762dcf4d4fe28cfbc87f9
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
@@ -319,7 +319,7 @@ F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2
|
||||
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
|
||||
F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0
|
||||
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
||||
F src/pcache1.c b800e90896640bb0d1b0f6baa34fb059ca3b8b2e
|
||||
F src/pcache1.c 3f4c87cf913f2de8189026d9a5223ddaf55eaf6b
|
||||
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
|
||||
F src/pragma.h b8632d7cdda7b25323fa580e3e558a4f0d4502cc
|
||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||
@@ -332,7 +332,7 @@ F src/shell.c 8af3cced094aebb5f57a8ad739b9dafc7867eed7
|
||||
F src/sqlite.h.in 3d951bf985839de7fcf4d3f69568bb4df2641abe
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h be1a718b7d2ce40ceba725ae92c8eb5f18003066
|
||||
F src/sqliteInt.h bc2cb1755150fc0b490d1af23ac2911b03f2f92d
|
||||
F src/sqliteInt.h d8d420d66a5c403b119696159b69f71cd53840ce
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
|
||||
@@ -843,9 +843,9 @@ F test/mallocL.test 252ddc7eb4fbf75364eab17b938816085ff1fc17
|
||||
F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
|
||||
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
F test/memdb.test fcb5297b321b562084fc79d64d5a12a1cd2b639b
|
||||
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
|
||||
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
|
||||
F test/memsubsys1.test 690d142525a7d31efb638b0d232e25fac3afeb1a
|
||||
F test/memsubsys1.test 1733c617e246642db5bf3b9f78c18e2b14fac96c
|
||||
F test/memsubsys2.test 3a1c1a9de48e5726faa85108b02459fae8cb9ee9
|
||||
F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
|
||||
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
|
||||
@@ -900,7 +900,7 @@ F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
|
||||
F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
|
||||
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
|
||||
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
||||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/pcache2.test ec3ae192f444ee6a0a80d1fd80d99695d884bfb3
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 6a88fd9ca15b804e9c20990773262ca67494058f
|
||||
F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2
|
||||
@@ -1005,7 +1005,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c 2e8f367c5fe5e0c3df24a157e17cb2f75c1b88c7
|
||||
F test/speedtest1.c 54f211994e2fb5b3f7c5c82137378f46ca89aae8
|
||||
F test/spellfix.test 0597065ff57042df1f138e6a2611ae19c2698135
|
||||
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
|
||||
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
|
||||
@@ -1364,7 +1364,8 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 6ace73541ae48aeb19e0c2d9f6772d032d0a7eae
|
||||
R 8adde983bcb4c45839c171b768ffd3b9
|
||||
P b27a47fef995f0ab2516e6ca779711cab1f50fb9 c1e2ed0ef4d3436d19d3203c5fb553caac53659e
|
||||
R 0716d0744f0e72c8cdadbca41133bc14
|
||||
T +closed c1e2ed0ef4d3436d19d3203c5fb553caac53659e
|
||||
U drh
|
||||
Z b9cf714cb314f182c61af66a54b1bb68
|
||||
Z eea1350426d30f63377f69d37a46ee1a
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
b27a47fef995f0ab2516e6ca779711cab1f50fb9
|
||||
5348ffc3fda5168c1e9e14aa88b0c6aedbda7c94
|
||||
+1
-1
@@ -9119,7 +9119,7 @@ static int checkTreePage(
|
||||
assert( (u32)i<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
size = get2byte(&data[i+2]);
|
||||
assert( (u32)(i+size)<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
btreeHeapInsert(heap, (i<<16)|(i+size-1));
|
||||
btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
|
||||
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
|
||||
** big-endian integer which is the offset in the b-tree page of the next
|
||||
** freeblock in the chain, or zero if the freeblock is the last on the
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
0, /* nScratch */
|
||||
(void*)0, /* pPage */
|
||||
0, /* szPage */
|
||||
0, /* nPage */
|
||||
SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */
|
||||
0, /* mxParserStack */
|
||||
0, /* sharedCacheEnabled */
|
||||
SQLITE_SORTER_PMASZ, /* szPma */
|
||||
|
||||
+153
-79
@@ -41,7 +41,8 @@
|
||||
**
|
||||
** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained
|
||||
** using a separate memory allocation from the database page content. This
|
||||
** seeks to overcome the "clownfoot" problem of allocating a few bytes more
|
||||
** seeks to overcome the "clownshoe" problem (also called "internal
|
||||
** fragmentation" in academic literature) of allocating a few bytes more
|
||||
** than a power of two with the memory allocator rounding up to the next
|
||||
** power of two, and leaving the rounded-up space unused.
|
||||
**
|
||||
@@ -50,8 +51,35 @@
|
||||
**
|
||||
** The pcache.c and pager.c modules deal pointers to PgHdr objects.
|
||||
** The btree.c module deals with pointers to MemPage objects.
|
||||
**
|
||||
** SOURCE OF PAGE CACHE MEMORY:
|
||||
**
|
||||
** Memory for a page might come from any of three sources:
|
||||
**
|
||||
** (1) The general-purpose memory allocator - sqlite3Malloc()
|
||||
** (2) Global page-cache memory provided using sqlite3_config() with
|
||||
** SQLITE_CONFIG_PAGECACHE.
|
||||
** (3) PCache-local bulk allocation.
|
||||
**
|
||||
** The third case is a chunk of heap memory (defaulting to 100 pages worth)
|
||||
** that is allocated when the page cache is created. The size of the local
|
||||
** bulk allocation can be adjusted using
|
||||
**
|
||||
** sqlite3_config(SQLITE_CONFIG_PCACHE, 0, 0, N).
|
||||
**
|
||||
** If N is positive, then N pages worth of memory are allocated using a single
|
||||
** sqlite3Malloc() call and that memory is used for the first N pages allocated.
|
||||
** Or if N is negative, then -1024*N bytes of memory are allocated and used
|
||||
** for as many pages as can be accomodated.
|
||||
**
|
||||
** Only one of (2) or (3) can be used. Once the memory available to (2) or
|
||||
** (3) is exhausted, subsequent allocations fail over to the general-purpose
|
||||
** memory allocator (1).
|
||||
**
|
||||
** Earlier versions of SQLite used only methods (1) and (2). But experiments
|
||||
** show that method (3) with N==100 provides about a 5% performance boost for
|
||||
** common workloads.
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
||||
typedef struct PCache1 PCache1;
|
||||
@@ -105,8 +133,9 @@ struct PCache1 {
|
||||
** The PGroup mutex must be held when accessing nMax.
|
||||
*/
|
||||
PGroup *pGroup; /* PGroup this cache belongs to */
|
||||
int szPage; /* Size of allocated pages in bytes */
|
||||
int szExtra; /* Size of extra space in bytes */
|
||||
int szPage; /* Size of database content section */
|
||||
int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */
|
||||
int szAlloc; /* Total size of one pcache line */
|
||||
int bPurgeable; /* True if cache is purgeable */
|
||||
unsigned int nMin; /* Minimum number of pages reserved */
|
||||
unsigned int nMax; /* Configured "cache_size" value */
|
||||
@@ -120,6 +149,8 @@ struct PCache1 {
|
||||
unsigned int nPage; /* Total number of pages in apHash */
|
||||
unsigned int nHash; /* Number of slots in apHash[] */
|
||||
PgHdr1 **apHash; /* Hash table for fast lookup by key */
|
||||
PgHdr1 *pFree; /* List of unused pcache-local pages */
|
||||
void *pBulk; /* Bulk memory used by pcache-local */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -132,6 +163,7 @@ 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 */
|
||||
@@ -139,8 +171,8 @@ struct PgHdr1 {
|
||||
};
|
||||
|
||||
/*
|
||||
** Free slots in the allocator used to divide up the buffer provided using
|
||||
** the SQLITE_CONFIG_PAGECACHE mechanism.
|
||||
** Free slots in the allocator used to divide up the global page cache
|
||||
** buffer provided using the SQLITE_CONFIG_PAGECACHE mechanism.
|
||||
*/
|
||||
struct PgFreeslot {
|
||||
PgFreeslot *pNext; /* Next free slot */
|
||||
@@ -158,10 +190,11 @@ static SQLITE_WSD struct PCacheGlobal {
|
||||
** The nFreeSlot and pFree values do require mutex protection.
|
||||
*/
|
||||
int isInit; /* True if initialized */
|
||||
int separateCache; /* Use a new PGroup for each PCache */
|
||||
int szSlot; /* Size of each free slot */
|
||||
int nSlot; /* The number of pcache slots */
|
||||
int nReserve; /* Try to keep nFreeSlot above this */
|
||||
void *pStart, *pEnd; /* Bounds of pagecache malloc range */
|
||||
void *pStart, *pEnd; /* Bounds of global page cache memory */
|
||||
/* Above requires no mutex. Use mutex below for variable that follow. */
|
||||
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
|
||||
PgFreeslot *pFree; /* Free page blocks */
|
||||
@@ -208,6 +241,7 @@ static SQLITE_WSD struct PCacheGlobal {
|
||||
void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
|
||||
if( pcache1.isInit ){
|
||||
PgFreeslot *p;
|
||||
if( pBuf==0 ) sz = n = 0;
|
||||
sz = ROUNDDOWN8(sz);
|
||||
pcache1.szSlot = sz;
|
||||
pcache1.nSlot = pcache1.nFreeSlot = n;
|
||||
@@ -272,9 +306,9 @@ static void *pcache1Alloc(int nByte){
|
||||
/*
|
||||
** Free an allocated buffer obtained from pcache1Alloc().
|
||||
*/
|
||||
static int pcache1Free(void *p){
|
||||
static void pcache1Free(void *p){
|
||||
int nFreed = 0;
|
||||
if( p==0 ) return 0;
|
||||
if( p==0 ) return;
|
||||
if( p>=pcache1.pStart && p<pcache1.pEnd ){
|
||||
PgFreeslot *pSlot;
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
@@ -289,15 +323,14 @@ static int pcache1Free(void *p){
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
|
||||
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
||||
nFreed = sqlite3MallocSize(p);
|
||||
#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
nFreed = sqlite3MallocSize(p);
|
||||
sqlite3_mutex_enter(pcache1.mutex);
|
||||
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed);
|
||||
sqlite3_mutex_leave(pcache1.mutex);
|
||||
#endif
|
||||
sqlite3_free(p);
|
||||
}
|
||||
return nFreed;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
@@ -325,54 +358,65 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
|
||||
PgHdr1 *p = 0;
|
||||
void *pPg;
|
||||
|
||||
/* The group mutex must be released before pcache1Alloc() is called. This
|
||||
** is because it may call sqlite3_release_memory(), which assumes that
|
||||
** this mutex is not held. */
|
||||
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
|
||||
pcache1LeaveMutex(pCache->pGroup);
|
||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||
pPg = pcache1Alloc(pCache->szPage);
|
||||
p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
|
||||
if( !pPg || !p ){
|
||||
pcache1Free(pPg);
|
||||
sqlite3_free(p);
|
||||
pPg = 0;
|
||||
}
|
||||
#else
|
||||
pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra);
|
||||
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
|
||||
if( pCache->pFree ){
|
||||
p = pCache->pFree;
|
||||
pCache->pFree = p->pNext;
|
||||
p->pNext = 0;
|
||||
}else{
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
/* The group mutex must be released before pcache1Alloc() is called. This
|
||||
** is because it might call sqlite3_release_memory(), which assumes that
|
||||
** this mutex is not held. */
|
||||
assert( pcache1.separateCache==0 );
|
||||
assert( pCache->pGroup==&pcache1.grp );
|
||||
pcache1LeaveMutex(pCache->pGroup);
|
||||
#endif
|
||||
pcache1EnterMutex(pCache->pGroup);
|
||||
|
||||
if( pPg ){
|
||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||
pPg = pcache1Alloc(pCache->szPage);
|
||||
p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
|
||||
if( !pPg || !p ){
|
||||
pcache1Free(pPg);
|
||||
sqlite3_free(p);
|
||||
pPg = 0;
|
||||
}
|
||||
#else
|
||||
pPg = pcache1Alloc(pCache->szAlloc);
|
||||
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
pcache1EnterMutex(pCache->pGroup);
|
||||
#endif
|
||||
if( pPg==0 ) return 0;
|
||||
p->page.pBuf = pPg;
|
||||
p->page.pExtra = &p[1];
|
||||
if( pCache->bPurgeable ){
|
||||
pCache->pGroup->nCurrentPage++;
|
||||
}
|
||||
return p;
|
||||
p->isBulkLocal = 0;
|
||||
}
|
||||
return 0;
|
||||
if( pCache->bPurgeable ){
|
||||
pCache->pGroup->nCurrentPage++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free a page object allocated by pcache1AllocPage().
|
||||
**
|
||||
** The pointer is allowed to be NULL, which is prudent. But it turns out
|
||||
** that the current implementation happens to never call this routine
|
||||
** with a NULL pointer, so we mark the NULL test with ALWAYS().
|
||||
*/
|
||||
static void pcache1FreePage(PgHdr1 *p){
|
||||
if( ALWAYS(p) ){
|
||||
PCache1 *pCache = p->pCache;
|
||||
assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
|
||||
PCache1 *pCache;
|
||||
assert( p!=0 );
|
||||
pCache = p->pCache;
|
||||
assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
|
||||
if( p->isBulkLocal ){
|
||||
p->pNext = pCache->pFree;
|
||||
pCache->pFree = p;
|
||||
}else{
|
||||
pcache1Free(p->page.pBuf);
|
||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||
sqlite3_free(p);
|
||||
#endif
|
||||
if( pCache->bPurgeable ){
|
||||
pCache->pGroup->nCurrentPage--;
|
||||
}
|
||||
}
|
||||
if( pCache->bPurgeable ){
|
||||
pCache->pGroup->nCurrentPage--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,6 +616,31 @@ static int pcache1Init(void *NotUsed){
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
assert( pcache1.isInit==0 );
|
||||
memset(&pcache1, 0, sizeof(pcache1));
|
||||
|
||||
|
||||
/*
|
||||
** The pcache1.separateCache variable is true if each PCache has its own
|
||||
** private PGroup (mode-1). pcache1.separateCache is false if the single
|
||||
** PGroup in pcache1.grp is used for all page caches (mode-2).
|
||||
**
|
||||
** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
|
||||
**
|
||||
** * Use a unified cache in single-threaded applications that have
|
||||
** configured a start-time buffer for use as page-cache memory using
|
||||
** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL
|
||||
** pBuf argument.
|
||||
**
|
||||
** * Otherwise use separate caches (mode-1)
|
||||
*/
|
||||
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
|
||||
pcache1.separateCache = 0;
|
||||
#elif SQLITE_THREADSAFE
|
||||
pcache1.separateCache = sqlite3GlobalConfig.pPage==0
|
||||
|| sqlite3GlobalConfig.bCoreMutex>0;
|
||||
#else
|
||||
pcache1.separateCache = sqlite3GlobalConfig.pPage==0;
|
||||
#endif
|
||||
|
||||
#if SQLITE_THREADSAFE
|
||||
if( sqlite3GlobalConfig.bCoreMutex ){
|
||||
pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
|
||||
@@ -607,31 +676,13 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
|
||||
PGroup *pGroup; /* The group the new page cache will belong to */
|
||||
int sz; /* Bytes of memory required to allocate the new cache */
|
||||
|
||||
/*
|
||||
** The separateCache variable is true if each PCache has its own private
|
||||
** PGroup. In other words, separateCache is true for mode (1) where no
|
||||
** mutexing is required.
|
||||
**
|
||||
** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
|
||||
**
|
||||
** * Always use a unified cache in single-threaded applications
|
||||
**
|
||||
** * Otherwise (if multi-threaded and ENABLE_MEMORY_MANAGEMENT is off)
|
||||
** use separate caches (mode-1)
|
||||
*/
|
||||
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
|
||||
const int separateCache = 0;
|
||||
#else
|
||||
int separateCache = sqlite3GlobalConfig.bCoreMutex>0;
|
||||
#endif
|
||||
|
||||
assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
|
||||
assert( szExtra < 300 );
|
||||
|
||||
sz = sizeof(PCache1) + sizeof(PGroup)*separateCache;
|
||||
sz = sizeof(PCache1) + sizeof(PGroup)*pcache1.separateCache;
|
||||
pCache = (PCache1 *)sqlite3MallocZero(sz);
|
||||
if( pCache ){
|
||||
if( separateCache ){
|
||||
if( pcache1.separateCache ){
|
||||
pGroup = (PGroup*)&pCache[1];
|
||||
pGroup->mxPinned = 10;
|
||||
}else{
|
||||
@@ -640,6 +691,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
|
||||
pCache->pGroup = pGroup;
|
||||
pCache->szPage = szPage;
|
||||
pCache->szExtra = szExtra;
|
||||
pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1));
|
||||
pCache->bPurgeable = (bPurgeable ? 1 : 0);
|
||||
pcache1EnterMutex(pGroup);
|
||||
pcache1ResizeHash(pCache);
|
||||
@@ -649,6 +701,36 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
|
||||
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
|
||||
}
|
||||
pcache1LeaveMutex(pGroup);
|
||||
/* Try to initialize the local bulk pagecache line allocation if using
|
||||
** separate caches and if nPage!=0 */
|
||||
if( pcache1.separateCache
|
||||
&& sqlite3GlobalConfig.nPage!=0
|
||||
&& sqlite3GlobalConfig.pPage==0
|
||||
){
|
||||
int szBulk;
|
||||
char *zBulk;
|
||||
sqlite3BeginBenignMalloc();
|
||||
if( sqlite3GlobalConfig.nPage>0 ){
|
||||
szBulk = pCache->szAlloc * sqlite3GlobalConfig.nPage;
|
||||
}else{
|
||||
szBulk = -1024*sqlite3GlobalConfig.nPage;
|
||||
}
|
||||
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
|
||||
sqlite3EndBenignMalloc();
|
||||
if( zBulk ){
|
||||
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
|
||||
int i;
|
||||
for(i=0; i<nBulk; i++){
|
||||
PgHdr1 *pX = (PgHdr1*)&zBulk[szPage];
|
||||
pX->page.pBuf = zBulk;
|
||||
pX->page.pExtra = &pX[1];
|
||||
pX->isBulkLocal = 1;
|
||||
pX->pNext = pCache->pFree;
|
||||
pCache->pFree = pX;
|
||||
zBulk += pCache->szAlloc;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( pCache->nHash==0 ){
|
||||
pcache1Destroy((sqlite3_pcache*)pCache);
|
||||
pCache = 0;
|
||||
@@ -742,26 +824,17 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
||||
assert( pCache->nHash>0 && pCache->apHash );
|
||||
|
||||
/* Step 4. Try to recycle a page. */
|
||||
if( pCache->bPurgeable && pGroup->pLruTail && (
|
||||
(pCache->nPage+1>=pCache->nMax)
|
||||
|| pGroup->nCurrentPage>=pGroup->nMaxPage
|
||||
|| pcache1UnderMemoryPressure(pCache)
|
||||
)){
|
||||
if( pCache->bPurgeable
|
||||
&& pGroup->pLruTail
|
||||
&& ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache))
|
||||
){
|
||||
PCache1 *pOther;
|
||||
pPage = pGroup->pLruTail;
|
||||
assert( pPage->isPinned==0 );
|
||||
pcache1RemoveFromHash(pPage, 0);
|
||||
pcache1PinPage(pPage);
|
||||
pOther = pPage->pCache;
|
||||
|
||||
/* We want to verify that szPage and szExtra are the same for pOther
|
||||
** and pCache. Assert that we can verify this by comparing sums. */
|
||||
assert( (pCache->szPage & (pCache->szPage-1))==0 && pCache->szPage>=512 );
|
||||
assert( pCache->szExtra<512 );
|
||||
assert( (pOther->szPage & (pOther->szPage-1))==0 && pOther->szPage>=512 );
|
||||
assert( pOther->szExtra<512 );
|
||||
|
||||
if( pOther->szPage+pOther->szExtra != pCache->szPage+pCache->szExtra ){
|
||||
if( pOther->szAlloc != pCache->szAlloc ){
|
||||
pcache1FreePage(pPage);
|
||||
pPage = 0;
|
||||
}else{
|
||||
@@ -1037,6 +1110,7 @@ static void pcache1Destroy(sqlite3_pcache *p){
|
||||
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
|
||||
pcache1EnforceMaxPage(pGroup);
|
||||
pcache1LeaveMutex(pGroup);
|
||||
sqlite3_free(pCache->pBulk);
|
||||
sqlite3_free(pCache->apHash);
|
||||
sqlite3_free(pCache);
|
||||
}
|
||||
@@ -1092,7 +1166,7 @@ int sqlite3PcacheReleaseMemory(int nReq){
|
||||
int nFree = 0;
|
||||
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
|
||||
assert( sqlite3_mutex_notheld(pcache1.mutex) );
|
||||
if( pcache1.pStart==0 ){
|
||||
if( sqlite3GlobalConfig.nPage==0 ){
|
||||
PgHdr1 *p;
|
||||
pcache1EnterMutex(&pcache1.grp);
|
||||
while( (nReq<0 || nFree<nReq) && ((p=pcache1.grp.pLruTail)!=0) ){
|
||||
|
||||
@@ -509,6 +509,16 @@
|
||||
# define SQLITE_MAX_WORKER_THREADS SQLITE_DEFAULT_WORKER_THREADS
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The default initial allocation for the pagecache when using separate
|
||||
** pagecaches for each database connection. A positive number is the
|
||||
** number of pages. A negative number N translations means that a buffer
|
||||
** of -1024*N bytes is allocated and used for as many pages as it will hold.
|
||||
*/
|
||||
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
|
||||
# define SQLITE_DEFAULT_PCACHE_INITSZ 100
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** GCC does not define the offsetof() macro so we'll have to do it
|
||||
|
||||
+3
-4
@@ -419,11 +419,10 @@ ifcapable autovacuum {
|
||||
INSERT INTO t1 VALUES(randstr(1000,1000));
|
||||
INSERT INTO t1 VALUES(randstr(1000,1000));
|
||||
}
|
||||
set memused [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
||||
set pgovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 1]
|
||||
set before [db one {PRAGMA page_count}]
|
||||
execsql { DELETE FROM t1 }
|
||||
set memused2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
|
||||
expr {($memused2 + 2048 < $memused) || $pgovfl==0}
|
||||
set after [db one {PRAGMA page_count}]
|
||||
expr {$before>$after}
|
||||
} {1}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ set xtra_size 290
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_lookaside 0 0
|
||||
sqlite3_config_pagecache 0 0
|
||||
sqlite3_initialize
|
||||
reset_highwater_marks
|
||||
build_test_db memsubsys1-1 {PRAGMA page_size=1024}
|
||||
@@ -115,10 +116,10 @@ do_test memsubsys1-2.5 {
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache [expr 512+$xtra_size] 20
|
||||
sqlite3_config singlethread
|
||||
sqlite3_initialize
|
||||
reset_highwater_marks
|
||||
build_test_db memsubsys1-3.1 {PRAGMA page_size=1024}
|
||||
#show_memstats
|
||||
do_test memsubsys1-3.1.3 {
|
||||
set pg_used [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0] 2]
|
||||
} 0
|
||||
@@ -312,6 +313,7 @@ sqlite3_config_memstatus 1
|
||||
sqlite3_config_pagecache 0 0
|
||||
sqlite3_config_scratch 0 0
|
||||
sqlite3_config_lookaside 100 500
|
||||
sqlite3_config serialized
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
finish_test
|
||||
|
||||
@@ -24,6 +24,7 @@ do_test pcache2-1.1 {
|
||||
sqlite3_reset_auto_extension
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache 6000 100
|
||||
sqlite3_config singlethread
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
sqlite3_status SQLITE_STATUS_PAGECACHE_USED 1
|
||||
@@ -73,6 +74,7 @@ catch {db2 close}
|
||||
sqlite3_reset_auto_extension
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_pagecache 0 0
|
||||
sqlite3_config serialized
|
||||
sqlite3_initialize
|
||||
autoinstall_test_functions
|
||||
|
||||
|
||||
+8
-4
@@ -1177,6 +1177,7 @@ int main(int argc, char **argv){
|
||||
int noSync = 0; /* True for --nosync */
|
||||
int pageSize = 0; /* Desired page size. 0 means default */
|
||||
int nPCache = 0, szPCache = 0;/* --pcache configuration */
|
||||
int doPCache = 0; /* True if --pcache is seen */
|
||||
int nScratch = 0, szScratch=0;/* --scratch configuration */
|
||||
int showStats = 0; /* True for --stats */
|
||||
int nThread = 0; /* --threads value */
|
||||
@@ -1251,6 +1252,7 @@ int main(int argc, char **argv){
|
||||
if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
|
||||
nPCache = integerValue(argv[i+1]);
|
||||
szPCache = integerValue(argv[i+2]);
|
||||
doPCache = 1;
|
||||
i += 2;
|
||||
}else if( strcmp(z,"primarykey")==0 ){
|
||||
g.zPK = "PRIMARY KEY";
|
||||
@@ -1317,10 +1319,12 @@ int main(int argc, char **argv){
|
||||
rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
|
||||
if( rc ) fatal_error("heap configuration failed: %d\n", rc);
|
||||
}
|
||||
if( nPCache>0 && szPCache>0 ){
|
||||
pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
|
||||
if( pPCache==0 ) fatal_error("cannot allocate %lld-byte pcache\n",
|
||||
nPCache*(sqlite3_int64)szPCache);
|
||||
if( doPCache ){
|
||||
if( nPCache>0 && szPCache>0 ){
|
||||
pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
|
||||
if( pPCache==0 ) fatal_error("cannot allocate %lld-byte pcache\n",
|
||||
nPCache*(sqlite3_int64)szPCache);
|
||||
}
|
||||
rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
|
||||
if( rc ) fatal_error("pcache configuration failed: %d\n", rc);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user