/ Check-in [b60cc11e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Performance optimizations in sqlite3PcacheFetch().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b60cc11ef775c23a2245d9e7a00dab34013f3ccb
User & Date: drh 2014-02-03 17:04:29
Context
2014-02-04
15:55
Rearrange fields in the Parse object for a tighter packing, resulting in an 8% size reduction on x64. check-in: 3e1a3f68 user: drh tags: trunk
2014-02-03
17:04
Performance optimizations in sqlite3PcacheFetch(). check-in: b60cc11e user: drh tags: trunk
14:04
Provide hints to the btree layer Next and Previous primitives to let them know if they can be no-ops if the underlying index is unique. check-in: 6c643e45 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pcache.c.

    19     19   struct PCache {
    20     20     PgHdr *pDirty, *pDirtyTail;         /* List of dirty pages in LRU order */
    21     21     PgHdr *pSynced;                     /* Last synced page in dirty page list */
    22     22     int nRef;                           /* Number of referenced pages */
    23     23     int szCache;                        /* Configured cache size */
    24     24     int szPage;                         /* Size of every page in this cache */
    25     25     int szExtra;                        /* Size of extra space for each page */
    26         -  int bPurgeable;                     /* True if pages are on backing store */
           26  +  u8 bPurgeable;                      /* True if pages are on backing store */
           27  +  u8 eCreate;                         /* eCreate value for for xFetch() */
    27     28     int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
    28     29     void *pStress;                      /* Argument to xStress */
    29     30     sqlite3_pcache *pCache;             /* Pluggable cache module */
    30     31     PgHdr *pPage1;                      /* Reference to page 1 */
    31     32   };
    32     33   
    33     34   /*
................................................................................
    86     87       p->pDirtyTail = pPage->pDirtyPrev;
    87     88     }
    88     89     if( pPage->pDirtyPrev ){
    89     90       pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
    90     91     }else{
    91     92       assert( pPage==p->pDirty );
    92     93       p->pDirty = pPage->pDirtyNext;
           94  +    if( p->pDirty==0 && p->bPurgeable ){
           95  +      assert( p->eCreate==1 );
           96  +      p->eCreate = 2;
           97  +    }
    93     98     }
    94     99     pPage->pDirtyNext = 0;
    95    100     pPage->pDirtyPrev = 0;
    96    101   
    97    102     expensive_assert( pcacheCheckSynced(p) );
    98    103   }
    99    104   
................................................................................
   106    111   
   107    112     assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
   108    113   
   109    114     pPage->pDirtyNext = p->pDirty;
   110    115     if( pPage->pDirtyNext ){
   111    116       assert( pPage->pDirtyNext->pDirtyPrev==0 );
   112    117       pPage->pDirtyNext->pDirtyPrev = pPage;
          118  +  }else if( p->bPurgeable ){
          119  +    assert( p->eCreate==2 );
          120  +    p->eCreate = 1;
   113    121     }
   114    122     p->pDirty = pPage;
   115    123     if( !p->pDirtyTail ){
   116    124       p->pDirtyTail = pPage;
   117    125     }
   118    126     if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
   119    127       p->pSynced = pPage;
................................................................................
   175    183     void *pStress,               /* Argument to xStress */
   176    184     PCache *p                    /* Preallocated space for the PCache */
   177    185   ){
   178    186     memset(p, 0, sizeof(PCache));
   179    187     p->szPage = szPage;
   180    188     p->szExtra = szExtra;
   181    189     p->bPurgeable = bPurgeable;
          190  +  p->eCreate = 2;
   182    191     p->xStress = xStress;
   183    192     p->pStress = pStress;
   184    193     p->szCache = 100;
   185    194   }
   186    195   
   187    196   /*
   188    197   ** Change the page size for PCache object. The caller must ensure that there
................................................................................
   214    223   */
   215    224   int sqlite3PcacheFetch(
   216    225     PCache *pCache,       /* Obtain the page from this cache */
   217    226     Pgno pgno,            /* Page number to obtain */
   218    227     int createFlag,       /* If true, create page if it does not exist already */
   219    228     PgHdr **ppPage        /* Write the page here */
   220    229   ){
   221         -  sqlite3_pcache_page *pPage = 0;
          230  +  sqlite3_pcache_page *pPage;
   222    231     PgHdr *pPgHdr = 0;
   223    232     int eCreate;
   224    233   
   225    234     assert( pCache!=0 );
   226    235     assert( createFlag==1 || createFlag==0 );
   227    236     assert( pgno>0 );
   228    237   
   229    238     /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
   230    239     ** allocate it now.
   231    240     */
   232         -  if( !pCache->pCache && createFlag ){
          241  +  if( !pCache->pCache ){
   233    242       sqlite3_pcache *p;
          243  +    if( !createFlag ){
          244  +      *ppPage = 0;
          245  +      return SQLITE_OK;
          246  +    }
   234    247       p = sqlite3GlobalConfig.pcache2.xCreate(
   235    248           pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
   236    249       );
   237    250       if( !p ){
   238    251         return SQLITE_NOMEM;
   239    252       }
   240    253       sqlite3GlobalConfig.pcache2.xCachesize(p, numberOfCachePages(pCache));
   241    254       pCache->pCache = p;
   242    255     }
   243    256   
   244         -  eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
   245         -  if( pCache->pCache ){
   246         -    pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
   247         -  }
   248         -
          257  +  /* eCreate defines what to do if the page does not exist.
          258  +  **    0     Do not allocate a new page.  (createFlag==0)
          259  +  **    1     Allocate a new page if doing so is inexpensive.
          260  +  **          (createFlag==1 AND bPurgeable AND pDirty)
          261  +  **    2     Allocate a new page even it doing so is difficult.
          262  +  **          (createFlag==1 AND !(bPurgeable AND pDirty)
          263  +  */
          264  +  eCreate = createFlag==0 ? 0 : pCache->eCreate;
          265  +  assert( (createFlag*(1+(!pCache->bPurgeable||!pCache->pDirty)))==eCreate );
          266  +  pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
   249    267     if( !pPage && eCreate==1 ){
   250    268       PgHdr *pPg;
   251    269   
   252    270       /* Find a dirty page to write-out and recycle. First try to find a 
   253    271       ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
   254    272       ** cleared), but if that is not possible settle for any other 
   255    273       ** unreferenced dirty page.