Compare commits

...

1 Commits

Author SHA1 Message Date
drh 0e98cdda22 This is a failed attempt to optimize the usage of the page cache in
sqlite3BtreeIndexMoveto() by deferring calls to sqlite3PagerUnref() for
child pages of the btree until we are sure those pages will not be reused.
The code does not work in two senses:  (1)  Many tests still fail.
(2) The performance gain is less than 2 million cycles and does not seem
worth the extra risk and complication.

FossilOrigin-Name: 84731a1fd25bd74c8f326a8a8ce3921831eb3d73872564b973bbd81aa406333d
2023-06-21 18:12:07 +00:00
3 changed files with 81 additions and 17 deletions
+9 -6
View File
@@ -1,5 +1,5 @@
C Add\sthe\s--pcachetrace\soption\sto\sthe\sCLI.
D 2023-06-21T14:11:25.888
C This\sis\sa\sfailed\sattempt\sto\soptimize\sthe\susage\sof\sthe\spage\scache\sin\nsqlite3BtreeIndexMoveto()\sby\sdeferring\scalls\sto\ssqlite3PagerUnref()\sfor\nchild\spages\sof\sthe\sbtree\suntil\swe\sare\ssure\sthose\spages\swill\snot\sbe\sreused.\nThe\scode\sdoes\snot\swork\sin\stwo\ssenses:\s\s(1)\s\sMany\stests\sstill\sfail.\n(2)\sThe\sperformance\sgain\sis\sless\sthan\s2\smillion\scycles\sand\sdoes\snot\sseem\nworth\sthe\sextra\srisk\sand\scomplication.
D 2023-06-21T18:12:07.803
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -576,7 +576,7 @@ F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
F src/btree.c 481666a3dd26b1cb16a9e9baaa3f6b17cab52a1d7a5836e5dcf5b45b85d4a51d
F src/btree.c 9a505e73aa1a7ce96c3e6b5480485a0bca83248c9e79f63f0481444b459e50a0
F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
F src/btreeInt.h 3b4eff7155c0cea6971dc51f62e3529934a15a6640ec607dd42a767e379cb3a9
F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4
@@ -2041,8 +2041,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P f94f3021cde1d46373ee8fc8e5028d7507a937240c59cf0d0d19ab22acbd3c41
R d23fbd106a98c76f065fa8c0590bcfbb
P 61dfa92b44ad38a7aac76a09e167819ce5d0acace3e06ba9ed17b3264cc043c1
R 92ef9d4b2ad4bcd79b4a344e5a5e7673
T *branch * pcache-opt
T *sym-pcache-opt *
T -sym-trunk *
U drh
Z 6142bb2a618d1d23b62eb525e555db78
Z 279ebc4b1e0c74835cf97ad5712d1d20
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
61dfa92b44ad38a7aac76a09e167819ce5d0acace3e06ba9ed17b3264cc043c1
84731a1fd25bd74c8f326a8a8ce3921831eb3d73872564b973bbd81aa406333d
+71 -10
View File
@@ -5900,6 +5900,7 @@ int sqlite3BtreeIndexMoveto(
){
int rc;
RecordCompare xRecordCompare;
int bNeedUnref; /* Deferred Unref() calls for pCur->apPage[] */
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
@@ -5949,19 +5950,43 @@ int sqlite3BtreeIndexMoveto(
if( !pCur->pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
bNeedUnref = 0;
goto bypass_moveto_root; /* Start search on the current page */
}
pIdxKey->errCode = SQLITE_OK;
}
rc = moveToRoot(pCur);
if( rc ){
if( rc==SQLITE_EMPTY ){
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
*pRes = -1;
return SQLITE_OK;
if( pCur->eState==CURSOR_VALID
&& pCur->iPage>0
&& pCur->apPage[0]->nCell>0
){
/* This block is similar to moveToRoot() except that it does not
** call releasePageNotNull() on the child pages found in the cursor.
** The pCur->apPage[x] pointers for x>=1 up to x==bNeedUnref
** remain valid and available for reuse. This means that the state of
** the BtCursor object is technical invalid when bNeedUnref>0. This
** routine must invoke releasePageNotNull() on apPage[] entries that
** are not reused prior to existing this function, in order to bring
** the cursor back into a valid state.
*/
bNeedUnref = pCur->iPage;
pCur->apPage[bNeedUnref] = pCur->pPage;
pCur->iPage = 0;
pCur->pPage = pCur->apPage[0];
pCur->ix = 0;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
}else{
bNeedUnref = 0;
rc = moveToRoot(pCur);
if( rc ){
if( rc==SQLITE_EMPTY ){
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
*pRes = -1;
return SQLITE_OK;
}
return rc;
}
return rc;
}
bypass_moveto_root:
@@ -6087,12 +6112,48 @@ bypass_moveto_root:
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
pCur->ix = (u16)lwr;
rc = moveToChild(pCur, chldPg);
if( rc ) break;
/* The following is similar to an in-lined version of
**
** pCur->ix = (u16)lwr;
** rc = moveToChild(pCur, chldPg);
**
** But with the additional feature that pCur->apPage[] entries
** that have had their Unref() calls deferred might be reused.
** Reusing an apPage[] entry bypasses a lot of look-up and
** initialization logic and hence saves many CPU cycles.
*/
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
assert( bNeedUnref==0 );
return SQLITE_CORRUPT_BKPT;
}
pCur->aiIdx[pCur->iPage] = (u16)lwr;
pCur->apPage[pCur->iPage] = pCur->pPage;
pCur->ix = 0;
pCur->iPage++;
if( bNeedUnref && pCur->apPage[pCur->iPage]->pgno==chldPg ){
pCur->pPage = pCur->apPage[pCur->iPage];
}else{
if( bNeedUnref ){
while( bNeedUnref>=pCur->iPage ){
releasePageNotNull(pCur->apPage[bNeedUnref--]);
}
bNeedUnref = 0;
}
rc = getAndInitPage(pCur->pBt, chldPg, &pCur->pPage, pCur,
pCur->curPagerFlags);
if( rc ) break;
}
}
moveto_index_finish:
pCur->info.nSize = 0;
if( bNeedUnref ){
while( bNeedUnref>pCur->iPage ){
releasePageNotNull(pCur->apPage[bNeedUnref--]);
}
}
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
return rc;
}