]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
This is a failed attempt to optimize the usage of the page cache in pcache-opt
authordrh <>
Wed, 21 Jun 2023 18:12:07 +0000 (18:12 +0000)
committerdrh <>
Wed, 21 Jun 2023 18:12:07 +0000 (18:12 +0000)
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

manifest
manifest.uuid
src/btree.c

index 98ea0d3fbe8b0c6b018985072905688eae1954f6..dc91ad0d8adef03f81a66c7b89b180cd44e5503e 100644 (file)
--- 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.
index 8a1232451f51058422c5bad81a9abf724b14b23a..bc176e0d8c941f54a234fe9ecf6cc3a4667f8cea 100644 (file)
@@ -1 +1 @@
-61dfa92b44ad38a7aac76a09e167819ce5d0acace3e06ba9ed17b3264cc043c1
\ No newline at end of file
+84731a1fd25bd74c8f326a8a8ce3921831eb3d73872564b973bbd81aa406333d
\ No newline at end of file
index 7f79327324a9f9ada4412161119e72ee8980b49a..491b614a06d42cd2a907bd703e7f26b1521d0a5a 100644 (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;
 }