现在的位置: 首页 > 综合 > 正文

sqlite的page cache

2014年09月05日 ⁄ 综合 ⁄ 共 4809字 ⁄ 字号 评论关闭

这部分的结构体在sqlite中定义了相似的两组,区别是名字后面加了个数字1,使的阅读起来非常不方便。后面加1的是内部定义;没加1的相当于接口,是给程序使用的。而且结构体中存在相互指向,使用起来也许比较方便,但抽象性不高

/*
** Every page in the cache is controlled by an instance of the following
** structure.
*/
struct PgHdr {
  void *pData;                   /* Content of this page 用于存放数据*/
  void *pExtra;                  /* Extra content */
  PgHdr *pDirty;                 /* Transient list of dirty pages */
  Pgno pgno;                     /* Page number for this page */
  Pager *pPager;                 /* The pager this page is part of */
#ifdef SQLITE_CHECK_PAGES
  u32 pageHash;                  /* Hash of page content */
#endif
  u16 flags;                     /* PGHDR flags defined below */

  /**********************************************************************
  ** Elements above are public.  All that follows is private to pcache.c
  ** and should not be accessed by other modules.
  */
  i16 nRef;                      /* Number of users of this page */
  PCache *pCache;                /* Cache that owns this page  指向cache列表*/

  PgHdr *pDirtyNext;             /* Next element in list of dirty pages  和下面的一起指向PCache中*/
  PgHdr *pDirtyPrev;             /* Previous element in list of dirty pages */
};
这就是page在内存中的page head

 

 

struct PCache {
  PgHdr *pDirty, *pDirtyTail;         /* List of dirty pages in LRU order  和PgHdr中的pDirtyNext pDirtyPrev一起使用*/
  PgHdr *pSynced;                     /* Last synced page in dirty page list */
  int nRef;                           /* Number of referenced pages */
  int nMax;                           /* Configured cache size */
  int szPage;                         /* Size of every page in this cache */
  int szExtra;                        /* Size of extra space for each page */
  int bPurgeable;                     /* True if pages are on backing store */
  int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
  void *pStress;                      /* Argument to xStress */
  sqlite3_pcache *pCache;             /* Pluggable cache module  把向PCache1 指向cache的真正实现*/
  PgHdr *pPage1;                      /* Reference to page 1 */
};

cache的定义,在这一层上,是没有内存淘汰算法的,只是记录一些信息

 

/*
** Global data used by this cache.
*/
static SQLITE_WSD struct PCacheGlobal {
  sqlite3_mutex *mutex;               /* static mutex MUTEX_STATIC_LRU */

  int nMaxPage;                       /* Sum of nMaxPage for purgeable caches */
  int nMinPage;                       /* Sum of nMinPage for purgeable caches */
  int nCurrentPage;                   /* Number of purgeable pages allocated */
  PgHdr1 *pLruHead, *pLruTail;        /* LRU list of unpinned pages */

  /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
  int szSlot;                         /* Size of each free slot */
  void *pStart, *pEnd;                /* Bounds of pagecache malloc range 指向预先分配的内存的起始和结束位置 */
  PgFreeslot *pFree;                  /* Free page blocks 使用时转化为, 这没有用union结构体,而是强制转化 */
  int isInit;                         /* True if initialized */
} pcache1_g;

 

这是cache的全局结构了,内存中只存在一个的全局变量pcache1。

这种分配策略不是每次分配内存时都通过malloc获得,而是把系统启动时分配的一块大内存,分配成PCacheGlobal ->szSlot大小的多个页面,用PCacheGlobal ->pFree链表连起来,每次申请时先从这里面取,释放时归还。当申请的,可通过unpin和pin不把内存归还到链表中,而是放入pLruHead, pLruTail组成的LRU链表中,形成LRU的内存淘汰算法,链表LRU很简单,就是把刚使用的接入链头,每次重用都是从链尾开始。

 

/* Pointers to structures of this type are cast and returned as
** opaque sqlite3_pcache* handles
*/
struct PCache1 {
  /* Cache configuration parameters. Page size (szPage) and the purgeable
  ** flag (bPurgeable) are set when the cache is created. nMax may be
  ** modified at any time by a call to the pcache1CacheSize() method.
  ** The global mutex must be held when accessing nMax.
  */
  int szPage;                         /* Size of allocated pages in bytes */
  int bPurgeable;                     /* True if cache is purgeable */
  unsigned int nMin;                  /* Minimum number of pages reserved */
  unsigned int nMax;                  /* Configured "cache_size" value */

  /* Hash table of all pages. The following variables may only be accessed
  ** when the accessor is holding the global mutex (see pcache1EnterMutex()
  ** and pcache1LeaveMutex()).
  */
  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  根据page number形成的HASH表,HASH值相同的组                                                     成单链表*/

   unsigned int iMaxKey;               /* Largest key seen since xTruncate() */
};

 

在内部层次的cache结构,对外是不可见的

/*
** Each cache entry is represented by an instance of the following
** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
** directly before this structure in memory (see the PGHDR1_TO_PAGE()
** macro below).
*/
struct PgHdr1 {
  unsigned int iKey;             /* Key value (page number) */
  PgHdr1 *pNext;                 /* Next in hash table chain */
  PCache1 *pCache;               /* Cache that currently owns this page */
  PgHdr1 *pLruNext;              /* Next in LRU list of unpinned pages 形成PCacheGlobal的LRU链表 */
  PgHdr1 *pLruPrev;              /* Previous in LRU list of unpinned pages */
};

 

在内部层次的page header结构,用在PCache1中的HASH表

 

/*
** Free slots in the allocator used to divide up the buffer provided using
** the SQLITE_CONFIG_PAGECACHE mechanism.
*/
struct PgFreeslot {
  PgFreeslot *pNext;  /* Next free slot  */
};

 

 

分配cache的时候,是从PCache->PCache1->PCacheGlobal 这个过程

 

抱歉!评论已关闭.