Patch the sqlite3PagerWrite() method in the Pager to run a bit faster.
FossilOrigin-Name: c63311e2f3344363a5ed99838fb5850004eaee30
This commit is contained in:
parent
efbf044583
commit
f063e08fd9
12
manifest
12
manifest
@ -1,5 +1,5 @@
|
||||
C Faster\simplementation\sof\spcache1Fetch()
|
||||
D 2014-08-23T23:15:31.233
|
||||
C Patch\sthe\ssqlite3PagerWrite()\smethod\sin\sthe\sPager\sto\srun\sa\sbit\sfaster.
|
||||
D 2014-08-24T01:32:43.379
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -211,7 +211,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
||||
F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542
|
||||
F src/os_win.c d067fce558a5032e6e6afe62899e5397bf63cf3e
|
||||
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
|
||||
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
|
||||
F src/pager.c c831b0df879114915c08dc5a0188f9f22c48403b
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
|
||||
F src/pcache.c da602c5447051705cab41604bf3276815eb569d0
|
||||
@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P bd41d394d48516eb7d8ddc46abdcb427aa80173e
|
||||
R d2491d65f44f8709d1d156c840c25703
|
||||
P 0371cc3bb07448bcd64fd671f3e71bb7f30deb4d
|
||||
R 2fe545d9c9446b3adf94c91625adc119
|
||||
U drh
|
||||
Z 15bb2365f5f8da3e5de34ee820ad0674
|
||||
Z 79e99766e8b4bdebd57118e507ef67dc
|
||||
|
@ -1 +1 @@
|
||||
0371cc3bb07448bcd64fd671f3e71bb7f30deb4d
|
||||
c63311e2f3344363a5ed99838fb5850004eaee30
|
185
src/pager.c
185
src/pager.c
@ -5772,6 +5772,97 @@ static int pager_write(PgHdr *pPg){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a variant of sqlite3PagerWrite() that runs when the sector size
|
||||
** is larger than the page size. SQLite makes the (reasonable) assumption that
|
||||
** all bytes of a sector are written together by hardware. Hence, all bytes of
|
||||
** a sector need to be journalled in case of a power loss in the middle of
|
||||
** a write.
|
||||
**
|
||||
** Usually, the sector size is less than or equal to the page size, in which
|
||||
** case pages can be individually written. This routine only runs in the exceptional
|
||||
** case where the page size is smaller than the sector size.
|
||||
*/
|
||||
static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Pgno nPageCount; /* Total number of pages in database file */
|
||||
Pgno pg1; /* First page of the sector pPg is located on. */
|
||||
int nPage = 0; /* Number of pages starting at pg1 to journal */
|
||||
int ii; /* Loop counter */
|
||||
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
|
||||
Pager *pPager = pPg->pPager; /* The pager that owns pPg */
|
||||
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
|
||||
|
||||
/* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
|
||||
** a journal header to be written between the pages journaled by
|
||||
** this function.
|
||||
*/
|
||||
assert( !MEMDB );
|
||||
assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
|
||||
pPager->doNotSpill |= SPILLFLAG_NOSYNC;
|
||||
|
||||
/* This trick assumes that both the page-size and sector-size are
|
||||
** an integer power of 2. It sets variable pg1 to the identifier
|
||||
** of the first page of the sector pPg is located on.
|
||||
*/
|
||||
pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
|
||||
|
||||
nPageCount = pPager->dbSize;
|
||||
if( pPg->pgno>nPageCount ){
|
||||
nPage = (pPg->pgno - pg1)+1;
|
||||
}else if( (pg1+nPagePerSector-1)>nPageCount ){
|
||||
nPage = nPageCount+1-pg1;
|
||||
}else{
|
||||
nPage = nPagePerSector;
|
||||
}
|
||||
assert(nPage>0);
|
||||
assert(pg1<=pPg->pgno);
|
||||
assert((pg1+nPage)>pPg->pgno);
|
||||
|
||||
for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
|
||||
Pgno pg = pg1+ii;
|
||||
PgHdr *pPage;
|
||||
if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
|
||||
if( pg!=PAGER_MJ_PGNO(pPager) ){
|
||||
rc = sqlite3PagerGet(pPager, pg, &pPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_write(pPage);
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}else if( (pPage = pager_lookup(pPager, pg))!=0 ){
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
|
||||
** starting at pg1, then it needs to be set for all of them. Because
|
||||
** writing to any of these nPage pages may damage the others, the
|
||||
** journal file must contain sync()ed copies of all of them
|
||||
** before any of them can be written out to the database file.
|
||||
*/
|
||||
if( rc==SQLITE_OK && needSync ){
|
||||
assert( !MEMDB );
|
||||
for(ii=0; ii<nPage; ii++){
|
||||
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
|
||||
if( pPage ){
|
||||
pPage->flags |= PGHDR_NEED_SYNC;
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
|
||||
pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Mark a data page as writeable. This routine must be called before
|
||||
** making changes to a page. The caller must check the return value
|
||||
@ -5786,96 +5877,16 @@ static int pager_write(PgHdr *pPg){
|
||||
** If an error occurs, SQLITE_NOMEM or an IO error code is returned
|
||||
** as appropriate. Otherwise, SQLITE_OK.
|
||||
*/
|
||||
int sqlite3PagerWrite(DbPage *pDbPage){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
PgHdr *pPg = pDbPage;
|
||||
Pager *pPager = pPg->pPager;
|
||||
|
||||
int sqlite3PagerWrite(PgHdr *pPg){
|
||||
assert( (pPg->flags & PGHDR_MMAP)==0 );
|
||||
assert( pPager->eState>=PAGER_WRITER_LOCKED );
|
||||
assert( pPager->eState!=PAGER_ERROR );
|
||||
assert( assert_pager_state(pPager) );
|
||||
|
||||
if( pPager->sectorSize > (u32)pPager->pageSize ){
|
||||
Pgno nPageCount; /* Total number of pages in database file */
|
||||
Pgno pg1; /* First page of the sector pPg is located on. */
|
||||
int nPage = 0; /* Number of pages starting at pg1 to journal */
|
||||
int ii; /* Loop counter */
|
||||
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
|
||||
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
|
||||
|
||||
/* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
|
||||
** a journal header to be written between the pages journaled by
|
||||
** this function.
|
||||
*/
|
||||
assert( !MEMDB );
|
||||
assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
|
||||
pPager->doNotSpill |= SPILLFLAG_NOSYNC;
|
||||
|
||||
/* This trick assumes that both the page-size and sector-size are
|
||||
** an integer power of 2. It sets variable pg1 to the identifier
|
||||
** of the first page of the sector pPg is located on.
|
||||
*/
|
||||
pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1;
|
||||
|
||||
nPageCount = pPager->dbSize;
|
||||
if( pPg->pgno>nPageCount ){
|
||||
nPage = (pPg->pgno - pg1)+1;
|
||||
}else if( (pg1+nPagePerSector-1)>nPageCount ){
|
||||
nPage = nPageCount+1-pg1;
|
||||
}else{
|
||||
nPage = nPagePerSector;
|
||||
}
|
||||
assert(nPage>0);
|
||||
assert(pg1<=pPg->pgno);
|
||||
assert((pg1+nPage)>pPg->pgno);
|
||||
|
||||
for(ii=0; ii<nPage && rc==SQLITE_OK; ii++){
|
||||
Pgno pg = pg1+ii;
|
||||
PgHdr *pPage;
|
||||
if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){
|
||||
if( pg!=PAGER_MJ_PGNO(pPager) ){
|
||||
rc = sqlite3PagerGet(pPager, pg, &pPage);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_write(pPage);
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}else if( (pPage = pager_lookup(pPager, pg))!=0 ){
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the PGHDR_NEED_SYNC flag is set for any of the nPage pages
|
||||
** starting at pg1, then it needs to be set for all of them. Because
|
||||
** writing to any of these nPage pages may damage the others, the
|
||||
** journal file must contain sync()ed copies of all of them
|
||||
** before any of them can be written out to the database file.
|
||||
*/
|
||||
if( rc==SQLITE_OK && needSync ){
|
||||
assert( !MEMDB );
|
||||
for(ii=0; ii<nPage; ii++){
|
||||
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
|
||||
if( pPage ){
|
||||
pPage->flags |= PGHDR_NEED_SYNC;
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
|
||||
pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
|
||||
assert( pPg->pPager->eState>=PAGER_WRITER_LOCKED );
|
||||
assert( pPg->pPager->eState!=PAGER_ERROR );
|
||||
assert( assert_pager_state(pPg->pPager) );
|
||||
if( pPg->pPager->sectorSize > (u32)pPg->pPager->pageSize ){
|
||||
return pagerWriteLargeSector(pPg);
|
||||
}else{
|
||||
rc = pager_write(pDbPage);
|
||||
return pager_write(pPg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user