1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Simplifications and performance improvement in pager_write().

FossilOrigin-Name: ab7aeeead395a05b91a921ef9ebe9252fffad667
This commit is contained in:
drh
2015-06-29 14:11:50 +00:00
parent c78ae916b9
commit 82ef8775c7
5 changed files with 101 additions and 94 deletions

View File

@@ -1,5 +1,5 @@
C Add\sthe\snew\sPGHDR_CLEAN\sbit\sto\sPgHdr.flags\sin\spcache.c.\s\sThis\sbit\sis\salways\nthe\sopposite\sof\sPGHDR_DIRTY.\s\sUse\sthe\sextra\sbit\sto\savoid\sa\scomparison\nfor\sa\ssmall\sperformance\sboost.
D 2015-06-29T04:21:15.041
C Simplifications\sand\sperformance\simprovement\sin\spager_write().
D 2015-06-29T14:11:50.755
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 285a0a234ed7610d431d91671c136098c2bd86a9
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -267,7 +267,7 @@ F src/analyze.c f89727c36f997bd2bf6c5e546c2f51dc94e6f2a4
F src/attach.c e944d0052b577703b9b83aac1638452ff42a8395
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 828b218d3fc39f8ce9c9c5f4de4106fe08c92303
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c ce342e156716fb64b9cf5c040260d0b47989f37b
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
@@ -314,7 +314,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c 23eb5f56fac54d8fe0cb204291f3b3b2d94f23fc
F src/os_win.c 27cc135e2d0b8b1e2e4944db1e2669a6a18fa0f8
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c db79b64a5498e2b3a72f0f6bc74faebe48da3e95
F src/pager.c 7e745749c375e3c35ef92051e2c1f7425cfcb3de
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
F src/pcache.c 994f15b465337a079feb04aac34c199dbc610247
@@ -332,7 +332,7 @@ F src/shell.c 8af3cced094aebb5f57a8ad739b9dafc7867eed7
F src/sqlite.h.in 76d2f5637eb795b6300d9dd3c3ec3632ffafd721
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h be1a718b7d2ce40ceba725ae92c8eb5f18003066
F src/sqliteInt.h d5df694bc33870e77fb08f389d12309597fe3059
F src/sqliteInt.h 89768198547bdd70a160e47643a0e493f711e8d0
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -1364,7 +1364,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 9b3a7281bd45994edf813a687e4b7a0761697929
R 07d5c4c2284ae7b5a16a8d841b25dd0d
P 8619fc346d9a5a66a3c4566b4cc032b6b6bf73fd
R 0aa742facd6911aa1b0a57fdcda4cf1c
U drh
Z fa5a6a0b1c08c7af0b43f02924ea472a
Z 44e348c1758353ed5733624fd5385fad

View File

@@ -1 +1 @@
8619fc346d9a5a66a3c4566b4cc032b6b6bf73fd
ab7aeeead395a05b91a921ef9ebe9252fffad667

View File

@@ -126,8 +126,8 @@ Bitvec *sqlite3BitvecCreate(u32 iSize){
** If p is NULL (if the bitmap has not been created) or if
** i is out of range, then return false.
*/
int sqlite3BitvecTest(Bitvec *p, u32 i){
if( p==0 ) return 0;
int sqlite3BitvecTestNotNull(Bitvec *p, u32 i){
assert( p!=0 );
i--;
if( i>=p->iSize ) return 0;
while( p->iDivisor ){
@@ -149,6 +149,9 @@ int sqlite3BitvecTest(Bitvec *p, u32 i){
return 0;
}
}
int sqlite3BitvecTest(Bitvec *p, u32 i){
return p!=0 && sqlite3BitvecTestNotNull(p,i);
}
/*
** Set the i-th bit. Return 0 on success and an error code if

View File

@@ -808,7 +808,7 @@ static const unsigned char aJournalMagic[] = {
**
** if( pPager->jfd->pMethods ){ ...
*/
#define isOpen(pFd) ((pFd)->pMethods)
#define isOpen(pFd) ((pFd)->pMethods!=0)
/*
** Return true if this pager uses a write-ahead log instead of the usual
@@ -1031,19 +1031,21 @@ static int subjRequiresPage(PgHdr *pPg){
int i;
for(i=0; i<pPager->nSavepoint; i++){
p = &pPager->aSavepoint[i];
if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
return 1;
}
}
return 0;
}
#ifdef SQLITE_DEBUG
/*
** Return true if the page is already in the journal file.
*/
static int pageInJournal(Pager *pPager, PgHdr *pPg){
return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno);
}
#endif
/*
** Read a 32-bit integer from the given file descriptor. Store the integer
@@ -5648,6 +5650,59 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
return rc;
}
/*
** Write page pPg onto the end of the rollback journal.
*/
static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
Pager *pPager = pPg->pPager;
int rc;
u32 cksum;
char *pData2;
i64 iOff = pPager->journalOff;
/* We should never write to the journal file the page that
** contains the database locks. The following assert verifies
** that we do not. */
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
assert( pPager->journalHdr<=pPager->journalOff );
CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
cksum = pager_cksum(pPager, (u8*)pData2);
/* Even if an IO or diskfull error occurs while journalling the
** page in the block above, set the need-sync flag for the page.
** Otherwise, when the transaction is rolled back, the logic in
** playback_one_page() will think that the page needs to be restored
** in the database file. And if an IO error occurs while doing so,
** then corruption may follow.
*/
pPg->flags |= PGHDR_NEED_SYNC;
rc = write32bits(pPager->jfd, iOff, pPg->pgno);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
if( rc!=SQLITE_OK ) return rc;
rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
if( rc!=SQLITE_OK ) return rc;
IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
pPager->journalOff, pPager->pageSize));
PAGER_INCR(sqlite3_pager_writej_count);
PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
PAGERID(pPager), pPg->pgno,
((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
pPager->journalOff += 8 + pPager->pageSize;
pPager->nRec++;
assert( pPager->pInJournal!=0 );
rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
testcase( rc==SQLITE_NOMEM );
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
rc |= addToSavepointBitvecs(pPager, pPg->pgno);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
return rc;
}
/*
** Mark a single data page as writeable. The page is written into the
** main journal or sub-journal as required. If the page is written into
@@ -5658,7 +5713,6 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
static int pager_write(PgHdr *pPg){
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
int inJournal;
/* This routine is not called unless a write-transaction has already
** been started. The journal file may or may not be open at this point.
@@ -5671,7 +5725,6 @@ static int pager_write(PgHdr *pPg){
assert( assert_pager_state(pPager) );
assert( pPager->errCode==0 );
assert( pPager->readOnly==0 );
CHECK_PAGE(pPg);
/* The journal file needs to be opened. Higher level routines have already
@@ -5690,91 +5743,41 @@ static int pager_write(PgHdr *pPg){
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
assert( assert_pager_state(pPager) );
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
/* Mark the page that is about to be modified as dirty. */
sqlite3PcacheMakeDirty(pPg);
inJournal = pageInJournal(pPager, pPg);
if( inJournal && (pPager->nSavepoint==0 || !subjRequiresPage(pPg)) ){
assert( !pagerUseWal(pPager) );
}else{
/* The transaction journal now exists and we have a RESERVED or an
** EXCLUSIVE lock on the main database file. Write the current page to
** the transaction journal if it is not there already.
*/
if( !inJournal && !pagerUseWal(pPager) ){
assert( pagerUseWal(pPager)==0 );
if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
u32 cksum;
char *pData2;
i64 iOff = pPager->journalOff;
/* We should never write to the journal file the page that
** contains the database locks. The following assert verifies
** that we do not. */
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
assert( pPager->journalHdr<=pPager->journalOff );
CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
cksum = pager_cksum(pPager, (u8*)pData2);
/* Even if an IO or diskfull error occurs while journalling the
** page in the block above, set the need-sync flag for the page.
** Otherwise, when the transaction is rolled back, the logic in
** playback_one_page() will think that the page needs to be restored
** in the database file. And if an IO error occurs while doing so,
** then corruption may follow.
*/
pPg->flags |= PGHDR_NEED_SYNC;
rc = write32bits(pPager->jfd, iOff, pPg->pgno);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize, iOff+4);
if( rc!=SQLITE_OK ) return rc;
rc = write32bits(pPager->jfd, iOff+pPager->pageSize+4, cksum);
if( rc!=SQLITE_OK ) return rc;
IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
pPager->journalOff, pPager->pageSize));
PAGER_INCR(sqlite3_pager_writej_count);
PAGERTRACE(("JOURNAL %d page %d needSync=%d hash(%08x)\n",
PAGERID(pPager), pPg->pgno,
((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg)));
pPager->journalOff += 8 + pPager->pageSize;
pPager->nRec++;
assert( pPager->pInJournal!=0 );
rc = sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
testcase( rc==SQLITE_NOMEM );
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
rc |= addToSavepointBitvecs(pPager, pPg->pgno);
if( rc!=SQLITE_OK ){
assert( rc==SQLITE_NOMEM );
return rc;
}
}else{
if( pPager->eState!=PAGER_WRITER_DBMOD ){
pPg->flags |= PGHDR_NEED_SYNC;
}
PAGERTRACE(("APPEND %d page %d needSync=%d\n",
PAGERID(pPager), pPg->pgno,
((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
/* If a rollback journal is in use, them make sure the page that is about
** to change is in the rollback journal, or if the page is a new page off
** then end of the file, make sure it is marked as PGHDR_NEED_SYNC.
*/
assert( (pPager->pInJournal!=0) == isOpen(pPager->jfd) );
if( pPager->pInJournal!=0 /* Journal open */
&& sqlite3BitvecTestNotNull(pPager->pInJournal, pPg->pgno)==0 /* pPg not in jrnl */
){
assert( pagerUseWal(pPager)==0 );
if( pPg->pgno<=pPager->dbOrigSize ){
rc = pagerAddPageToRollbackJournal(pPg);
if( rc!=SQLITE_OK ){
return rc;
}
}
/* If the statement journal is open and the page is not in it,
** then write the current page to the statement journal. Note that
** the statement journal format differs from the standard journal format
** in that it omits the checksums and the header.
*/
if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){
rc = subjournalPage(pPg);
}else{
if( pPager->eState!=PAGER_WRITER_DBMOD ){
pPg->flags |= PGHDR_NEED_SYNC;
}
PAGERTRACE(("APPEND %d page %d needSync=%d\n",
PAGERID(pPager), pPg->pgno,
((pPg->flags&PGHDR_NEED_SYNC)?1:0)));
}
}
/* Update the database size and return.
/* If the statement journal is open and the page is not in it,
** then write the page into the statement journal.
*/
if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){
rc = subjournalPage(pPg);
}
/* Update the database size and return. */
if( pPager->dbSize<pPg->pgno ){
pPager->dbSize = pPg->pgno;
}

View File

@@ -3238,6 +3238,7 @@ int sqlite3CodeOnce(Parse *);
Bitvec *sqlite3BitvecCreate(u32);
int sqlite3BitvecTest(Bitvec*, u32);
int sqlite3BitvecTestNotNull(Bitvec*, u32);
int sqlite3BitvecSet(Bitvec*, u32);
void sqlite3BitvecClear(Bitvec*, u32, void*);
void sqlite3BitvecDestroy(Bitvec*);