pcache lru 注释

main
yezhengmao 2023-06-28 18:35:25 +08:00
parent 6044cf0556
commit c08c2c1620
3 changed files with 50 additions and 50 deletions

View File

@ -167,13 +167,10 @@ char *sqlite3_temp_directory = 0;
char *sqlite3_data_directory = 0;
/*
** Initialize SQLite.
** SQLITE3
**
** This routine must be called to initialize the memory allocation,
** VFS, and mutex subsystems prior to doing any serious work with
** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
** sqlite3_open().
** SQLITE_OMIT_AUTOINIT
** VFSmutex
**
** This routine is a no-op except on its very first call for the process,
** or for the first call after a call to sqlite3_shutdown.

View File

@ -39,7 +39,7 @@
** pointers).
*/
struct PCache {
PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
PgHdr *pDirty, *pDirtyTail; /* LRU 顺序排列的脏页 */
PgHdr *pSynced; /* Last synced page in dirty page list */
i64 nRefSum; /* Sum of ref counts over all pages */
int szCache; /* Configured cache size */
@ -47,10 +47,10 @@ struct PCache {
int szPage; /* Size of every page in this cache */
int szExtra; /* Size of extra space for each page */
u8 bPurgeable; /* True if pages are on backing store */
u8 eCreate; /* eCreate value for for xFetch() */
u8 eCreate; /* xFetch 函数使用,是否创建页面 */
int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
void *pStress; /* Argument to xStress */
sqlite3_pcache *pCache; /* Pluggable cache module */
sqlite3_pcache *pCache; /* 可插拔的 cache 模块实现 */
};
/********************************** Test and Debug Logic **********************/
@ -403,17 +403,18 @@ sqlite3_pcache_page *sqlite3PcacheFetch(
assert( createFlag==3 || createFlag==0 );
assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) );
/* eCreate defines what to do if the page does not exist.
** 0 Do not allocate a new page. (createFlag==0)
** 1 Allocate a new page if doing so is inexpensive.
/* eCreate 定义页面不存在时的操作
** 0 . (createFlag==0)
** 1 .
** (createFlag==1 AND bPurgeable AND pDirty)
** 2 Allocate a new page even it doing so is difficult.
** 2 .
** (createFlag==1 AND !(bPurgeable AND pDirty)
*/
eCreate = createFlag & pCache->eCreate;
assert( eCreate==0 || eCreate==1 || eCreate==2 );
assert( createFlag==0 || pCache->eCreate==eCreate );
assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
/* 调用 pcache1.c 中的 pcache1Fetch 函数 */
pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno,
createFlag?" create":"",pRes));

View File

@ -119,16 +119,16 @@ struct PgHdr1 {
unsigned int iKey; /* Key value (page number) */
u16 isBulkLocal; /* This page from bulk local storage */
u16 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 circular LRU list of unpinned pages */
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
PgHdr1 *pNext; /* Hash 表中的 next */
PCache1 *pCache; /* 当前页面所属的 cache */
PgHdr1 *pLruNext; /* LRU 链表中的 next */
PgHdr1 *pLruPrev; /* LRU 链表中的 prev */
/* NB: pLruPrev is only valid if pLruNext!=0 */
};
/*
** A page is pinned if it is not on the LRU list. To be "pinned" means
** that the page is in active use and must not be deallocated.
** PINNED 使 LRU
** UNPINNED 使 LRU
*/
#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
@ -160,7 +160,7 @@ struct PGroup {
unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
unsigned int nMinPage; /* Sum of nMin for purgeable caches */
unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
unsigned int nPurgeable; /* Number of purgeable pages allocated */
unsigned int nPurgeable; /* 可替换页的数量 */
PgHdr1 lru; /* The beginning and end of the LRU list */
};
@ -180,11 +180,11 @@ struct PCache1 {
** The PGroup mutex must be held when accessing nMax.
*/
PGroup *pGroup; /* PGroup this cache belongs to */
unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */
int szPage; /* Size of database content section */
unsigned int *pnPurgeable; /* 指向 pGroup->nPurgeable 总可替换页数量 */
int szPage; /* 页面大小 */
int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */
int szAlloc; /* Total size of one pcache line */
int bPurgeable; /* True if cache is purgeable */
int szAlloc; /* 总大小,包含页面和元数据 */
int bPurgeable; /* 页面是否能被重用,即淘汰替换页内容 */
unsigned int nMin; /* Minimum number of pages reserved */
unsigned int nMax; /* Configured "cache_size" value */
unsigned int n90pct; /* nMax*9/10 */
@ -194,10 +194,10 @@ struct PCache1 {
/* Hash table of all pages. The following variables may only be accessed
** when the accessor is holding the PGroup mutex.
*/
unsigned int nRecyclable; /* Number of pages in the LRU list */
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 */
unsigned int nRecyclable; /* LRU 链表中剩余的节点 */
unsigned int nPage; /* Hash 表中的节点数量,即所有页数量 */
unsigned int nHash; /* Hash 表 slot 数量 */
PgHdr1 **apHash; /* Hash 表用于快速查找 key */
PgHdr1 *pFree; /* List of unused pcache-local pages */
void *pBulk; /* Bulk memory used by pcache-local */
};
@ -211,7 +211,7 @@ struct PgFreeslot {
};
/*
** Global data used by this cache.
** cache 使 - pcache1
*/
static SQLITE_WSD struct PCacheGlobal {
PGroup grp; /* The global PGroup for mode (2) */
@ -427,7 +427,7 @@ static int pcache1MemSize(void *p){
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
/*
** Allocate a new page object initially associated with cache pCache.
** cache
*/
static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
PgHdr1 *p = 0;
@ -541,6 +541,7 @@ static void pcache1ResizeHash(PCache1 *p){
assert( sqlite3_mutex_held(p->pGroup->mutex) );
/* 将 slot 扩大 2 倍 */
nNew = p->nHash*2;
if( nNew<256 ){
nNew = 256;
@ -551,6 +552,7 @@ static void pcache1ResizeHash(PCache1 *p){
apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
if( p->nHash ){ sqlite3EndBenignMalloc(); }
pcache1EnterMutex(p->pGroup);
/* 拷贝到新 hash table */
if( apNew ){
for(i=0; i<p->nHash; i++){
PgHdr1 *pPage;
@ -880,8 +882,10 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
PGroup *pGroup = pCache->pGroup;
PgHdr1 *pPage = 0;
/* Step 3: Abort if createFlag is 1 but the cache is nearly full */
/* Step 3: cache 已经快满了,但是任然请求分配新页,直接 abort */
/* 控制内存申请 */
assert( pCache->nPage >= pCache->nRecyclable );
/* nPinned: 使用中的页面 */
nPinned = pCache->nPage - pCache->nRecyclable;
assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
assert( pCache->n90pct == pCache->nMax*9/10 );
@ -892,11 +896,11 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
)){
return 0;
}
/* hash 优化,如果 hash 中节点数量比 slot 多,做一次 resize */
if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache);
assert( pCache->nHash>0 && pCache->apHash );
/* Step 4. Try to recycle a page. */
/* Step 4. page 是否能够重用 */
if( pCache->bPurgeable
&& !pGroup->lru.pLruPrev->isAnchor
&& ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache))
@ -915,8 +919,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
}
}
/* Step 5. If a usable page buffer has still not been found,
** attempt to allocate a new one.
/* Step 5. 任然没有 page 可用,申请新页
*/
if( !pPage ){
pPage = pcache1AllocPage(pCache, createFlag==1);
@ -941,14 +944,14 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
}
/*
** Implementation of the sqlite3_pcache.xFetch method.
** sqlite3_pcache.xFetch .
**
** Fetch a page by key value.
** key .
**
** Whether or not a new page may be allocated by this function depends on
** the value of the createFlag argument. 0 means do not allocate a new
** page. 1 means allocate a new page if space is easily available. 2
** means to try really hard to allocate a new page.
** createFlag cache
** 0
** 1
** 2
**
** For a non-purgeable cache (a cache used as the storage for an in-memory
** database) there is really no difference between createFlag 1 and 2. So
@ -994,10 +997,9 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
**
** 5. Otherwise, allocate and return a new page buffer.
**
** There are two versions of this routine. pcache1FetchWithMutex() is
** the general case. pcache1FetchNoMutex() is a faster implementation for
** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper
** invokes the appropriate routine.
** pcache1Fetch
** pcache1FetchWithMutex()
** pcache1FetchNoMutex() pGroup->mutex == NULL
*/
static PgHdr1 *pcache1FetchNoMutex(
sqlite3_pcache *p,
@ -1007,14 +1009,14 @@ static PgHdr1 *pcache1FetchNoMutex(
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = 0;
/* Step 1: Search the hash table for an existing entry. */
/* Step 1: 查找 hash 表key 是否存在 */
pPage = pCache->apHash[iKey % pCache->nHash];
while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; }
/* Step 2: If the page was found in the hash table, then return it.
** If the page was not in the hash table and createFlag is 0, abort.
** Otherwise (page not in hash and createFlag!=0) continue with
** subsequent steps to try to create the page. */
/* Step 2: 查找到该页,直接返回。]
** abort
**
*/
if( pPage ){
if( PAGE_IS_UNPINNED(pPage) ){
return pcache1PinPage(pPage);