From: drh <> Date: Wed, 21 Jun 2023 18:12:07 +0000 (+0000) Subject: This is a failed attempt to optimize the usage of the page cache in X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0e98cdda2230cf9030d6db47c963c70ac714fc29;p=thirdparty%2Fsqlite.git 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 --- diff --git a/manifest b/manifest index 98ea0d3fbe..dc91ad0d8a 100644 --- a/manifest +++ b/manifest @@ -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. diff --git a/manifest.uuid b/manifest.uuid index 8a1232451f..bc176e0d8c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -61dfa92b44ad38a7aac76a09e167819ce5d0acace3e06ba9ed17b3264cc043c1 \ No newline at end of file +84731a1fd25bd74c8f326a8a8ce3921831eb3d73872564b973bbd81aa406333d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 7f79327324..491b614a06 100644 --- a/src/btree.c +++ b/src/btree.c @@ -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; }