mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-10 01:02:56 +03:00
Patch the sqlite3PagerWrite() method in the Pager to run a bit faster.
FossilOrigin-Name: c63311e2f3344363a5ed99838fb5850004eaee30
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Faster\simplementation\sof\spcache1Fetch()
|
C Patch\sthe\ssqlite3PagerWrite()\smethod\sin\sthe\sPager\sto\srun\sa\sbit\sfaster.
|
||||||
D 2014-08-23T23:15:31.233
|
D 2014-08-24T01:32:43.379
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -211,7 +211,7 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
|||||||
F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542
|
F src/os_unix.c bd7df3094a60915c148517504c76df4fca24e542
|
||||||
F src/os_win.c d067fce558a5032e6e6afe62899e5397bf63cf3e
|
F src/os_win.c d067fce558a5032e6e6afe62899e5397bf63cf3e
|
||||||
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
|
F src/os_win.h 09e751b20bbc107ffbd46e13555dc73576d88e21
|
||||||
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
|
F src/pager.c c831b0df879114915c08dc5a0188f9f22c48403b
|
||||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||||
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
|
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
|
||||||
F src/pcache.c da602c5447051705cab41604bf3276815eb569d0
|
F src/pcache.c da602c5447051705cab41604bf3276815eb569d0
|
||||||
@@ -1188,7 +1188,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P bd41d394d48516eb7d8ddc46abdcb427aa80173e
|
P 0371cc3bb07448bcd64fd671f3e71bb7f30deb4d
|
||||||
R d2491d65f44f8709d1d156c840c25703
|
R 2fe545d9c9446b3adf94c91625adc119
|
||||||
U drh
|
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;
|
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
|
** Mark a data page as writeable. This routine must be called before
|
||||||
** making changes to a page. The caller must check the return value
|
** 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
|
** If an error occurs, SQLITE_NOMEM or an IO error code is returned
|
||||||
** as appropriate. Otherwise, SQLITE_OK.
|
** as appropriate. Otherwise, SQLITE_OK.
|
||||||
*/
|
*/
|
||||||
int sqlite3PagerWrite(DbPage *pDbPage){
|
int sqlite3PagerWrite(PgHdr *pPg){
|
||||||
int rc = SQLITE_OK;
|
|
||||||
|
|
||||||
PgHdr *pPg = pDbPage;
|
|
||||||
Pager *pPager = pPg->pPager;
|
|
||||||
|
|
||||||
assert( (pPg->flags & PGHDR_MMAP)==0 );
|
assert( (pPg->flags & PGHDR_MMAP)==0 );
|
||||||
assert( pPager->eState>=PAGER_WRITER_LOCKED );
|
assert( pPg->pPager->eState>=PAGER_WRITER_LOCKED );
|
||||||
assert( pPager->eState!=PAGER_ERROR );
|
assert( pPg->pPager->eState!=PAGER_ERROR );
|
||||||
assert( assert_pager_state(pPager) );
|
assert( assert_pager_state(pPg->pPager) );
|
||||||
|
if( pPg->pPager->sectorSize > (u32)pPg->pPager->pageSize ){
|
||||||
if( pPager->sectorSize > (u32)pPager->pageSize ){
|
return pagerWriteLargeSector(pPg);
|
||||||
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;
|
|
||||||
}else{
|
}else{
|
||||||
rc = pager_write(pDbPage);
|
return pager_write(pPg);
|
||||||
}
|
}
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user