SQLite

Check-in [9c0b9f8813]
Login

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

Overview
Comment:Optimization: When loading a new page into the cache, avoid redundant memset() calls to zero it. (CVS 6201)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9c0b9f881367871105965d4268e2f2cde7f4d884
User & Date: danielk1977 2009-01-23 16:45:01.000
Context
2009-01-24
09:56
Remove incorrect ALWAYS macro associated with empty IN() sets. Ticket #3602. (CVS 6202) (check-in: f3c09a0cb8 user: danielk1977 tags: trunk)
2009-01-23
16:45
Optimization: When loading a new page into the cache, avoid redundant memset() calls to zero it. (CVS 6201) (check-in: 9c0b9f8813 user: danielk1977 tags: trunk)
2009-01-22
23:04
Fix the VACUUM command so that it does not commit a transaction when it is mistakenly run within a transaction - it should leave the transaction open. (CVS 6200) (check-in: 75cc709be4 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/pager.c.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.557 2009/01/22 17:12:40 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"

/*
** Macros for troubleshooting.  Normally turned off
*/







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.558 2009/01/23 16:45:01 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"

/*
** Macros for troubleshooting.  Normally turned off
*/
3726
3727
3728
3729
3730
3731
3732

3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768


3769
3770
3771
3772
3773
3774
3775
  assert( pPager->state!=PAGER_UNLOCK );

  rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, &pPg);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  assert( pPg->pgno==pgno );

  if( pPg->pPager==0 ){
    /* The pager cache has created a new page. Its content needs to 
    ** be initialized.
    */
    int nMax;
    PAGER_INCR(pPager->nMiss);
    pPg->pPager = pPager;
    memset(pPg->pExtra, 0, pPager->nExtra);

    rc = sqlite3PagerPagecount(pPager, &nMax);
    if( rc!=SQLITE_OK ){
      sqlite3PagerUnref(pPg);
      return rc;
    }

    if( nMax<(int)pgno || MEMDB || noContent ){
      if( pgno>pPager->mxPgno ){
        sqlite3PagerUnref(pPg);
        return SQLITE_FULL;
      }
      memset(pPg->pData, 0, pPager->pageSize);
      if( noContent ){
        /* Failure to set the bits in the InJournal bit-vectors is benign.
        ** It merely means that we might do some extra work to journal a 
        ** page that does not need to be journaled.  Nevertheless, be sure 
        ** to test the case where a malloc error occurs while trying to set 
        ** a bit in a bit vector.
        */
        sqlite3BeginBenignMalloc();
        if( pgno<=pPager->dbOrigSize ){
          TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
          testcase( rc==SQLITE_NOMEM );
        }
        TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
        testcase( rc==SQLITE_NOMEM );
        sqlite3EndBenignMalloc();


      }
      IOTRACE(("ZERO %p %d\n", pPager, pgno));
    }else{
      assert( pPg->pPager==pPager );
      rc = readDbPage(pPg);
      if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
        pagerDropPage(pPg);







>







<












<















>
>







3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740

3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752

3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
  assert( pPager->state!=PAGER_UNLOCK );

  rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, &pPg);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  assert( pPg->pgno==pgno );
  assert( pPg->pPager==pPager || pPg->pPager==0 );
  if( pPg->pPager==0 ){
    /* The pager cache has created a new page. Its content needs to 
    ** be initialized.
    */
    int nMax;
    PAGER_INCR(pPager->nMiss);
    pPg->pPager = pPager;


    rc = sqlite3PagerPagecount(pPager, &nMax);
    if( rc!=SQLITE_OK ){
      sqlite3PagerUnref(pPg);
      return rc;
    }

    if( nMax<(int)pgno || MEMDB || noContent ){
      if( pgno>pPager->mxPgno ){
        sqlite3PagerUnref(pPg);
        return SQLITE_FULL;
      }

      if( noContent ){
        /* Failure to set the bits in the InJournal bit-vectors is benign.
        ** It merely means that we might do some extra work to journal a 
        ** page that does not need to be journaled.  Nevertheless, be sure 
        ** to test the case where a malloc error occurs while trying to set 
        ** a bit in a bit vector.
        */
        sqlite3BeginBenignMalloc();
        if( pgno<=pPager->dbOrigSize ){
          TESTONLY( rc = ) sqlite3BitvecSet(pPager->pInJournal, pgno);
          testcase( rc==SQLITE_NOMEM );
        }
        TESTONLY( rc = ) addToSavepointBitvecs(pPager, pgno);
        testcase( rc==SQLITE_NOMEM );
        sqlite3EndBenignMalloc();
      }else{
        memset(pPg->pData, 0, pPager->pageSize);
      }
      IOTRACE(("ZERO %p %d\n", pPager, pgno));
    }else{
      assert( pPg->pPager==pPager );
      rc = readDbPage(pPg);
      if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
        pagerDropPage(pPg);
Changes to src/pager.h.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem.  The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.96 2009/01/20 17:06:27 danielk1977 Exp $
*/

#ifndef _PAGER_H_
#define _PAGER_H_

/*
** Default maximum size for persistent journal files. A negative 







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem.  The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.97 2009/01/23 16:45:01 danielk1977 Exp $
*/

#ifndef _PAGER_H_
#define _PAGER_H_

/*
** Default maximum size for persistent journal files. A negative 
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
99
100
101
102
103
104
** that make up the Pager sub-system API. See source code comments for 
** a detailed description of each routine.
*/

/* Open and close a Pager connection. */ 
int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
int sqlite3PagerClose(Pager *pPager);


/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*));
int sqlite3PagerSetPagesize(Pager*, u16*);
int sqlite3PagerMaxPageCount(Pager*, int);
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
void sqlite3PagerSetCachesize(Pager*, int);
void sqlite3PagerSetSafetyLevel(Pager*,int,int);
int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerJournalMode(Pager *, int);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);

/* Functions used to obtain and release page references. */ 







>






<







84
85
86
87
88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
** that make up the Pager sub-system API. See source code comments for 
** a detailed description of each routine.
*/

/* Open and close a Pager connection. */ 
int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
int sqlite3PagerClose(Pager *pPager);
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);

/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*));
int sqlite3PagerSetPagesize(Pager*, u16*);
int sqlite3PagerMaxPageCount(Pager*, int);

void sqlite3PagerSetCachesize(Pager*, int);
void sqlite3PagerSetSafetyLevel(Pager*,int,int);
int sqlite3PagerLockingMode(Pager *, int);
int sqlite3PagerJournalMode(Pager *, int);
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);

/* Functions used to obtain and release page references. */ 
Changes to src/pcache.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2008 August 05
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements that page cache.
**
** @(#) $Id: pcache.c,v 1.42 2009/01/20 17:06:27 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** A complete page cache is an instance of this structure.
*/
struct PCache {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2008 August 05
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements that page cache.
**
** @(#) $Id: pcache.c,v 1.43 2009/01/23 16:45:01 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** A complete page cache is an instance of this structure.
*/
struct PCache {
257
258
259
260
261
262
263











264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
      }
    }

    pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2);
  }

  if( pPage ){











    if( 0==pPage->nRef ){
      pCache->nRef++;
    }
    pPage->nRef++;
    pPage->pData = (void*)&pPage[1];
    pPage->pExtra = (void*)&((char*)pPage->pData)[pCache->szPage];
    pPage->pCache = pCache;
    pPage->pgno = pgno;
    if( pgno==1 ){
      pCache->pPage1 = pPage;
    }
  }
  *ppPage = pPage;
  return (pPage==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
}







>
>
>
>
>
>
>
>
>
>
>




<
<
<
<







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278




279
280
281
282
283
284
285
      }
    }

    pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2);
  }

  if( pPage ){
    if( !pPage->pData ){
      memset(pPage, 0, sizeof(PgHdr) + pCache->szExtra);
      pPage->pExtra = (void*)&pPage[1];
      pPage->pData = (void *)&((char *)pPage)[sizeof(PgHdr) + pCache->szExtra];
      pPage->pCache = pCache;
      pPage->pgno = pgno;
    }
    assert( pPage->pCache==pCache );
    assert( pPage->pgno==pgno );
    assert( pPage->pExtra==(void *)&pPage[1] );

    if( 0==pPage->nRef ){
      pCache->nRef++;
    }
    pPage->nRef++;




    if( pgno==1 ){
      pCache->pPage1 = pPage;
    }
  }
  *ppPage = pPage;
  return (pPage==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
}
Changes to src/pcache1.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
**
** This file implements the default page cache implementation (the
** sqlite3_pcache interface). It also contains part of the implementation
** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
** If the default page cache implementation is overriden, then neither of
** these two features are available.
**
** @(#) $Id: pcache1.c,v 1.7 2009/01/07 15:18:21 danielk1977 Exp $
*/

#include "sqliteInt.h"

typedef struct PCache1 PCache1;
typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
**
** This file implements the default page cache implementation (the
** sqlite3_pcache interface). It also contains part of the implementation
** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
** If the default page cache implementation is overriden, then neither of
** these two features are available.
**
** @(#) $Id: pcache1.c,v 1.8 2009/01/23 16:45:01 danielk1977 Exp $
*/

#include "sqliteInt.h"

typedef struct PCache1 PCache1;
typedef struct PgHdr1 PgHdr1;
typedef struct PgFreeslot PgFreeslot;
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*
** Allocate a new page object initially associated with cache pCache.
*/
static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
  int nByte = sizeof(PgHdr1) + pCache->szPage;
  PgHdr1 *p = (PgHdr1 *)pcache1Alloc(nByte);
  if( p ){
    memset(p, 0, nByte);
    if( pCache->bPurgeable ){
      pcache1.nCurrentPage++;
    }
  }
  return p;
}








<







197
198
199
200
201
202
203

204
205
206
207
208
209
210
/*
** Allocate a new page object initially associated with cache pCache.
*/
static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
  int nByte = sizeof(PgHdr1) + pCache->szPage;
  PgHdr1 *p = (PgHdr1 *)pcache1Alloc(nByte);
  if( p ){

    if( pCache->bPurgeable ){
      pcache1.nCurrentPage++;
    }
  }
  return p;
}

546
547
548
549
550
551
552
553
554
555
556
557


558
559
560
561
562
563
564
  */
  if( !pPage ){
    pPage = pcache1AllocPage(pCache);
  }

  if( pPage ){
    unsigned int h = iKey % pCache->nHash;
    memset(pPage, 0, pCache->szPage + sizeof(PgHdr1));
    pCache->nPage++;
    pPage->iKey = iKey;
    pPage->pNext = pCache->apHash[h];
    pPage->pCache = pCache;


    pCache->apHash[h] = pPage;
  }

fetch_out:
  if( pPage && iKey>pCache->iMaxKey ){
    pCache->iMaxKey = iKey;
  }







|




>
>







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  */
  if( !pPage ){
    pPage = pcache1AllocPage(pCache);
  }

  if( pPage ){
    unsigned int h = iKey % pCache->nHash;
    *(void **)(PGHDR1_TO_PAGE(pPage)) = 0;
    pCache->nPage++;
    pPage->iKey = iKey;
    pPage->pNext = pCache->apHash[h];
    pPage->pCache = pCache;
    pPage->pLruPrev = 0;
    pPage->pLruNext = 0;
    pCache->apHash[h] = pPage;
  }

fetch_out:
  if( pPage && iKey>pCache->iMaxKey ){
    pCache->iMaxKey = iKey;
  }
Changes to src/sqlite.h.in.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.421 2008/12/30 06:24:58 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** on how SQLite interfaces are suppose to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
** @(#) $Id: sqlite.h.in,v 1.422 2009/01/23 16:45:01 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
**                SQLite is holding pinned pages that can be unpinned
**                by writing their contents to the database file (a
**                relatively expensive operation). In this situation the
**                cache implementation has two choices: it can return NULL,
**                in which case SQLite will attempt to unpin one or more 
**                pages before re-requesting the same page, or it can
**                allocate a new page and return a pointer to it. If a new
**                page is allocated, then it must be completely zeroed before 
**                it is returned.
**   <tr><td>2<td>If createFlag is set to 2, then SQLite is not holding any
**                pinned pages associated with the specific cache passed
**                as the first argument to xFetch() that can be unpinned. The
**                cache implementation should attempt to allocate a new
**                cache entry and return a pointer to it. Again, the new
**                page should be zeroed before it is returned. If the xFetch()
**                method returns NULL when createFlag==2, SQLite assumes that
**                a memory allocation failed and returns SQLITE_NOMEM to the
**                user.
** </table>
**
** xUnpin() is called by SQLite with a pointer to a currently pinned page
** as its second argument. If the third parameter, discard, is non-zero,
** then the page should be evicted from the cache. In this case SQLite 
** assumes that the next time the page is retrieved from the cache using
** the xFetch() method, it will be zeroed. If the discard parameter is







|
|




|
|
|
|
|







6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
**                SQLite is holding pinned pages that can be unpinned
**                by writing their contents to the database file (a
**                relatively expensive operation). In this situation the
**                cache implementation has two choices: it can return NULL,
**                in which case SQLite will attempt to unpin one or more 
**                pages before re-requesting the same page, or it can
**                allocate a new page and return a pointer to it. If a new
**                page is allocated, then the first sizeof(void*) bytes of
**                it (at least) must be zeroed before it is returned.
**   <tr><td>2<td>If createFlag is set to 2, then SQLite is not holding any
**                pinned pages associated with the specific cache passed
**                as the first argument to xFetch() that can be unpinned. The
**                cache implementation should attempt to allocate a new
**                cache entry and return a pointer to it. Again, the first
**                sizeof(void*) bytes of the page should be zeroed before 
**                it is returned. If the xFetch() method returns NULL when 
**                createFlag==2, SQLite assumes that a memory allocation 
**                failed and returns SQLITE_NOMEM to the user.
** </table>
**
** xUnpin() is called by SQLite with a pointer to a currently pinned page
** as its second argument. If the third parameter, discard, is non-zero,
** then the page should be evicted from the cache. In this case SQLite 
** assumes that the next time the page is retrieved from the cache using
** the xFetch() method, it will be zeroed. If the discard parameter is