/ Check-in [015302f1]
Login

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

Overview
Comment:Simplify the pcache by not keeping continuous track of page 1 but instead just loading page 1 on the rare occasions when it is actually needed.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 015302f15e46a087ec92f3644c6741600dbf4306
User & Date: drh 2015-06-26 02:41:31
Context
2015-06-26
13:31
Cache the most recently sqlite3_context used by OP_Function and reuse it on subsequent calls, if appropriate. This gives a noticable performance boost. Closed-Leaf check-in: 2f31bdd1 user: drh tags: function-ctx-cache
03:12
Fix harmless compiler warning in assert statement. check-in: 7097716c user: mistachkin tags: trunk
02:41
Simplify the pcache by not keeping continuous track of page 1 but instead just loading page 1 on the rare occasions when it is actually needed. check-in: 015302f1 user: drh tags: trunk
2015-06-25
23:52
Optimization to sqlite3_value_bytes() for the common case that does not require a data transformation. check-in: 8d79f3a1 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pcache.c.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
...
491
492
493
494
495
496
497
498




499
500

501
502
503
504
505
506
507
  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() */
  int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
  void *pStress;                      /* Argument to xStress */
  sqlite3_pcache *pCache;             /* Pluggable cache module */
  PgHdr *pPage1;                      /* Reference to page 1 */
};

/********************************** Linked List Management ********************/

/* Allowed values for second argument to pcacheManageDirtyList() */
#define PCACHE_DIRTYLIST_REMOVE   1    /* Remove pPage from dirty list */
#define PCACHE_DIRTYLIST_ADD      2    /* Add pPage to the dirty list */
................................................................................

/*
** Wrapper around the pluggable caches xUnpin method. If the cache is
** being used for an in-memory database, this function is a no-op.
*/
static void pcacheUnpin(PgHdr *p){
  if( p->pCache->bPurgeable ){
    if( p->pgno==1 ){
      p->pCache->pPage1 = 0;
    }
    sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
  }
}

/*
** Compute the number of pages of cache requested.  p->szCache is the
** cache size requested by the "PRAGMA cache_size" statement.
................................................................................
    );
    if( pNew==0 ) return SQLITE_NOMEM;
    sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
    if( pCache->pCache ){
      sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
    }
    pCache->pCache = pNew;
    pCache->pPage1 = 0;
    pCache->szPage = szPage;
  }
  return SQLITE_OK;
}

/*
** Try to obtain a page from the cache.
................................................................................
  if( !pPgHdr->pPage ){
    return pcacheFetchFinishWithInit(pCache, pgno, pPage);
  }
  if( 0==pPgHdr->nRef ){
    pCache->nRef++;
  }
  pPgHdr->nRef++;
  if( pgno==1 ){
    pCache->pPage1 = pPgHdr;
  }
  return pPgHdr;
}

/*
** Decrement the reference count on a page. If the page is clean and the
** reference count drops to 0, then it is made eligible for recycling.
*/
................................................................................
*/
void sqlite3PcacheDrop(PgHdr *p){
  assert( p->nRef==1 );
  if( p->flags&PGHDR_DIRTY ){
    pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
  }
  p->pCache->nRef--;
  if( p->pgno==1 ){
    p->pCache->pPage1 = 0;
  }
  sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1);
}

/*
** Make sure the page is marked as dirty. If it isn't dirty already,
** make it so.
*/
................................................................................
      */
      assert( p->pgno>0 );
      if( ALWAYS(p->pgno>pgno) ){
        assert( p->flags&PGHDR_DIRTY );
        sqlite3PcacheMakeClean(p);
      }
    }
    if( pgno==0 && pCache->pPage1 ){




      memset(pCache->pPage1->pData, 0, pCache->szPage);
      pgno = 1;

    }
    sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
  }
}

/*
** Close a cache.







<







 







<
<
<







 







<







 







<
<
<







 







<
<
<







 







|
>
>
>
>
|
|
>







24
25
26
27
28
29
30

31
32
33
34
35
36
37
...
101
102
103
104
105
106
107



108
109
110
111
112
113
114
...
193
194
195
196
197
198
199

200
201
202
203
204
205
206
...
350
351
352
353
354
355
356



357
358
359
360
361
362
363
...
390
391
392
393
394
395
396



397
398
399
400
401
402
403
...
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
  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() */
  int (*xStress)(void*,PgHdr*);       /* Call to try make a page clean */
  void *pStress;                      /* Argument to xStress */
  sqlite3_pcache *pCache;             /* Pluggable cache module */

};

/********************************** Linked List Management ********************/

/* Allowed values for second argument to pcacheManageDirtyList() */
#define PCACHE_DIRTYLIST_REMOVE   1    /* Remove pPage from dirty list */
#define PCACHE_DIRTYLIST_ADD      2    /* Add pPage to the dirty list */
................................................................................

/*
** Wrapper around the pluggable caches xUnpin method. If the cache is
** being used for an in-memory database, this function is a no-op.
*/
static void pcacheUnpin(PgHdr *p){
  if( p->pCache->bPurgeable ){



    sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
  }
}

/*
** Compute the number of pages of cache requested.  p->szCache is the
** cache size requested by the "PRAGMA cache_size" statement.
................................................................................
    );
    if( pNew==0 ) return SQLITE_NOMEM;
    sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
    if( pCache->pCache ){
      sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
    }
    pCache->pCache = pNew;

    pCache->szPage = szPage;
  }
  return SQLITE_OK;
}

/*
** Try to obtain a page from the cache.
................................................................................
  if( !pPgHdr->pPage ){
    return pcacheFetchFinishWithInit(pCache, pgno, pPage);
  }
  if( 0==pPgHdr->nRef ){
    pCache->nRef++;
  }
  pPgHdr->nRef++;



  return pPgHdr;
}

/*
** Decrement the reference count on a page. If the page is clean and the
** reference count drops to 0, then it is made eligible for recycling.
*/
................................................................................
*/
void sqlite3PcacheDrop(PgHdr *p){
  assert( p->nRef==1 );
  if( p->flags&PGHDR_DIRTY ){
    pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
  }
  p->pCache->nRef--;



  sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1);
}

/*
** Make sure the page is marked as dirty. If it isn't dirty already,
** make it so.
*/
................................................................................
      */
      assert( p->pgno>0 );
      if( ALWAYS(p->pgno>pgno) ){
        assert( p->flags&PGHDR_DIRTY );
        sqlite3PcacheMakeClean(p);
      }
    }
    if( pgno==0 && pCache->nRef ){
      sqlite3_pcache_page *pPage1;
      pPage1 = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache,1,0);
      if( ALWAYS(pPage1) ){  /* Page 1 is always available in cache, because
                             ** pCache->nRef>0 */
        memset(pPage1->pBuf, 0, pCache->szPage);
        pgno = 1;
      }
    }
    sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
  }
}

/*
** Close a cache.