1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Micro-optimizations in sqlite3BtreeNext() and sqlite3BtreePrevious().

FossilOrigin-Name: 839c7996eecd5480152c514555b9aa1121a69ce0
This commit is contained in:
drh
2014-09-01 13:29:32 +00:00
parent 31970cca38
commit ee6438df0b
3 changed files with 84 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
C Fix\sharmless\scompiler\swarnings\sfor\sMSVC. C Micro-optimizations\sin\ssqlite3BtreeNext()\sand\ssqlite3BtreePrevious().
D 2014-09-01T01:16:49.641 D 2014-09-01T13:29:32.250
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
@@ -168,7 +168,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4 F src/btmutex.c ec9d3f1295dafeb278c3830211cc5584132468f4
F src/btree.c 4737cb5bdb2eb8989cb292f6ff921f7ff45f0c46 F src/btree.c 4d0427bab54229030fc5b8577d2e5ffdc8129030
F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8 F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3 F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb F src/build.c 058e3aadb1376521ff291735237edf4c10f438fb
@@ -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 f61db04be4d7fb21b7f721647c37c45e283ffbea P 3ef3246120d72dffe469733bb21667a548af0a44
R fb90b1156ce26645b130e94c9528a286 R 8a87472d819e62a6d7e88f3d5e77ba23
U mistachkin U drh
Z ab89ed2842a9e03f7299dfc1fb42f5cb Z 5b0c8a527e1dec5d8cc1bbd203422489

View File

@@ -1 +1 @@
3ef3246120d72dffe469733bb21667a548af0a44 839c7996eecd5480152c514555b9aa1121a69ce0

View File

@@ -4513,17 +4513,16 @@ static int moveToRightmost(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) ); assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
pCur->aiIdx[pCur->iPage] = pPage->nCell; pCur->aiIdx[pCur->iPage] = pPage->nCell;
rc = moveToChild(pCur, pgno); rc = moveToChild(pCur, pgno);
if( rc ) return rc;
} }
if( rc==SQLITE_OK ){
pCur->aiIdx[pCur->iPage] = pPage->nCell-1; pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
pCur->info.nSize = 0; assert( pCur->info.nSize==0 );
pCur->curFlags &= ~BTCF_ValidNKey; assert( (pCur->curFlags & BTCF_ValidNKey)==0 );
} return SQLITE_OK;
return rc;
} }
/* Move the cursor to the first entry in the table. Return SQLITE_OK /* Move the cursor to the first entry in the table. Return SQLITE_OK
@@ -4843,6 +4842,12 @@ int sqlite3BtreeEof(BtCursor *pCur){
** was already pointing to the last entry in the database before ** was already pointing to the last entry in the database before
** this routine was called, then set *pRes=1. ** this routine was called, then set *pRes=1.
** **
** The main entry point is sqlite3BtreeNext(). That routine is optimized
** for the common case of merely incrementing the cell counter BtCursor.aiIdx
** to the next cell on the current page. The (slower) btreeNext() helper
** routine is called when it is necessary to move to a different page or
** to restore the cursor.
**
** The calling function will set *pRes to 0 or 1. The initial *pRes value ** The calling function will set *pRes to 0 or 1. The initial *pRes value
** will be 1 if the cursor being stepped corresponds to an SQL index and ** will be 1 if the cursor being stepped corresponds to an SQL index and
** if this routine could have been skipped if that SQL index had been ** if this routine could have been skipped if that SQL index had been
@@ -4852,20 +4857,18 @@ int sqlite3BtreeEof(BtCursor *pCur){
** SQLite btree implementation does not. (Note that the comdb2 btree ** SQLite btree implementation does not. (Note that the comdb2 btree
** implementation does use this hint, however.) ** implementation does use this hint, however.)
*/ */
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
int rc; int rc;
int idx; int idx;
MemPage *pPage; MemPage *pPage;
assert( cursorHoldsMutex(pCur) ); assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
assert( *pRes==0 );
if( pCur->eState!=CURSOR_VALID ){ if( pCur->eState!=CURSOR_VALID ){
invalidateOverflowCache(pCur); assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
rc = restoreCursorPosition(pCur); rc = restoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
*pRes = 0;
return rc; return rc;
} }
if( CURSOR_INVALID==pCur->eState ){ if( CURSOR_INVALID==pCur->eState ){
@@ -4877,7 +4880,6 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
pCur->eState = CURSOR_VALID; pCur->eState = CURSOR_VALID;
if( pCur->skipNext>0 ){ if( pCur->skipNext>0 ){
pCur->skipNext = 0; pCur->skipNext = 0;
*pRes = 0;
return SQLITE_OK; return SQLITE_OK;
} }
pCur->skipNext = 0; pCur->skipNext = 0;
@@ -4895,18 +4897,11 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
** page into more than one b-tree structure. */ ** page into more than one b-tree structure. */
testcase( idx>pPage->nCell ); testcase( idx>pPage->nCell );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( idx>=pPage->nCell ){ if( idx>=pPage->nCell ){
if( !pPage->leaf ){ if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
if( rc ){ if( rc ) return rc;
*pRes = 0; return moveToLeftmost(pCur);
return rc;
}
rc = moveToLeftmost(pCur);
*pRes = 0;
return rc;
} }
do{ do{
if( pCur->iPage==0 ){ if( pCur->iPage==0 ){
@@ -4917,22 +4912,39 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
moveToParent(pCur); moveToParent(pCur);
pPage = pCur->apPage[pCur->iPage]; pPage = pCur->apPage[pCur->iPage];
}while( pCur->aiIdx[pCur->iPage]>=pPage->nCell ); }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell );
*pRes = 0;
if( pPage->intKey ){ if( pPage->intKey ){
rc = sqlite3BtreeNext(pCur, pRes); return sqlite3BtreeNext(pCur, pRes);
}else{ }else{
rc = SQLITE_OK;
}
return rc;
}
*pRes = 0;
if( pPage->leaf ){
return SQLITE_OK; return SQLITE_OK;
} }
rc = moveToLeftmost(pCur); }
return rc; if( pPage->leaf ){
return SQLITE_OK;
}else{
return moveToLeftmost(pCur);
}
}
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
*pRes = 0;
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes);
pPage = pCur->apPage[pCur->iPage];
if( (++pCur->aiIdx[pCur->iPage])>=pPage->nCell ){
pCur->aiIdx[pCur->iPage]--;
return btreeNext(pCur, pRes);
}
if( pPage->leaf ){
return SQLITE_OK;
}else{
return moveToLeftmost(pCur);
}
} }
/* /*
** Step the cursor to the back to the previous entry in the database. If ** Step the cursor to the back to the previous entry in the database. If
@@ -4940,6 +4952,12 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
** was already pointing to the first entry in the database before ** was already pointing to the first entry in the database before
** this routine was called, then set *pRes=1. ** this routine was called, then set *pRes=1.
** **
** The main entry point is sqlite3BtreePrevious(). That routine is optimized
** for the common case of merely decrementing the cell counter BtCursor.aiIdx
** to the previous cell on the current page. The (slower) btreePrevious() helper
** routine is called when it is necessary to move to a different page or
** to restore the cursor.
**
** The calling function will set *pRes to 0 or 1. The initial *pRes value ** The calling function will set *pRes to 0 or 1. The initial *pRes value
** will be 1 if the cursor being stepped corresponds to an SQL index and ** will be 1 if the cursor being stepped corresponds to an SQL index and
** if this routine could have been skipped if that SQL index had been ** if this routine could have been skipped if that SQL index had been
@@ -4949,23 +4967,22 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
** SQLite btree implementation does not. (Note that the comdb2 btree ** SQLite btree implementation does not. (Note that the comdb2 btree
** implementation does use this hint, however.) ** implementation does use this hint, however.)
*/ */
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
int rc; int rc;
MemPage *pPage; MemPage *pPage;
assert( cursorHoldsMutex(pCur) ); assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 ); assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 ); assert( *pRes==0 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID ); assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl); assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
assert( pCur->info.nSize==0 );
if( pCur->eState!=CURSOR_VALID ){ if( pCur->eState!=CURSOR_VALID ){
if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){ assert( pCur->eState>=CURSOR_REQUIRESEEK );
rc = btreeRestoreCursorPosition(pCur); rc = btreeRestoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
*pRes = 0;
return rc; return rc;
} }
}
if( CURSOR_INVALID==pCur->eState ){ if( CURSOR_INVALID==pCur->eState ){
*pRes = 1; *pRes = 1;
return SQLITE_OK; return SQLITE_OK;
@@ -4975,7 +4992,6 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
pCur->eState = CURSOR_VALID; pCur->eState = CURSOR_VALID;
if( pCur->skipNext<0 ){ if( pCur->skipNext<0 ){
pCur->skipNext = 0; pCur->skipNext = 0;
*pRes = 0;
return SQLITE_OK; return SQLITE_OK;
} }
pCur->skipNext = 0; pCur->skipNext = 0;
@@ -4987,10 +5003,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
if( !pPage->leaf ){ if( !pPage->leaf ){
int idx = pCur->aiIdx[pCur->iPage]; int idx = pCur->aiIdx[pCur->iPage];
rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
if( rc ){ if( rc ) return rc;
*pRes = 0;
return rc;
}
rc = moveToRightmost(pCur); rc = moveToRightmost(pCur);
}else{ }else{
while( pCur->aiIdx[pCur->iPage]==0 ){ while( pCur->aiIdx[pCur->iPage]==0 ){
@@ -5001,8 +5014,8 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
} }
moveToParent(pCur); moveToParent(pCur);
} }
pCur->info.nSize = 0; assert( pCur->info.nSize==0 );
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl); assert( (pCur->curFlags & (BTCF_ValidNKey|BTCF_ValidOvfl))==0 );
pCur->aiIdx[pCur->iPage]--; pCur->aiIdx[pCur->iPage]--;
pPage = pCur->apPage[pCur->iPage]; pPage = pCur->apPage[pCur->iPage];
@@ -5012,9 +5025,25 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
rc = SQLITE_OK; rc = SQLITE_OK;
} }
} }
*pRes = 0;
return rc; return rc;
} }
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
*pRes = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
pCur->info.nSize = 0;
if( pCur->eState!=CURSOR_VALID
|| pCur->aiIdx[pCur->iPage]==0
|| pCur->apPage[pCur->iPage]->leaf==0
){
return btreePrevious(pCur, pRes);
}
pCur->aiIdx[pCur->iPage]--;
return SQLITE_OK;
}
/* /*
** Allocate a new page from the database file. ** Allocate a new page from the database file.