]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhance the pcache1PinPage() routine so that it called much less often and
authordrh <drh@noemail.net>
Fri, 13 Dec 2013 18:50:40 +0000 (18:50 +0000)
committerdrh <drh@noemail.net>
Fri, 13 Dec 2013 18:50:40 +0000 (18:50 +0000)
runs much faster in the cases when it is actually called.

FossilOrigin-Name: a845779cd31aec3204a6a9c776bd9c9f7d47dd24

manifest
manifest.uuid
src/pcache1.c

index 9255f89b3ad4ad08ce5a9d7dc02973e123df6f4d..89fa59f99354d0d67bd723b4ec138b43d53a2946 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Avoid\sunnecessary\scalls\sto\ssqlite3_free()\sfrom\swithin\ssqlite3VXPrintf().
-D 2013-12-13T16:42:18.070
+C Enhance\sthe\spcache1PinPage()\sroutine\sso\sthat\sit\scalled\smuch\sless\soften\sand\nruns\smuch\sfaster\sin\sthe\scases\swhen\sit\sis\sactually\scalled.
+D 2013-12-13T18:50:40.859
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -212,7 +212,7 @@ F src/pager.h 6a790b64a9ea79bc2c849bdefdd39e2344bca94a
 F src/parse.y acee1a9958539e21263362b194594c5255ad2fca
 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
-F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
+F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b
 F src/pragma.c 5ab7279d132143feb77f773688a24ab05da75fd7
 F src/prepare.c 359d1a1e9c9bd4488e4dd3a1aaaf2d2ebb9bb768
 F src/printf.c ba8b28e9d4ce984430e9f33f6ef1c85a1826d1dd
@@ -1146,7 +1146,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 9d347f547e7ba9590b0c68edf50a14ad94a2bb92
-R b5a32784d4c7409fae006d7d9202782e
+P e2a8b280e84c1f8fd6106d9427e1ad6cbcfccd10
+R 47d549dcdf3ed528411247342cb19e3a
 U drh
-Z f8a864e171b1e45dee7c898a5141e356
+Z da9f1c1b1e757ffeeb8c40974d788c01
index 604bc728a04d32c8fe0c1521552d0062ce462b98..18544568b9bf26d5eec2359922cfeaadbe7b1c22 100644 (file)
@@ -1 +1 @@
-e2a8b280e84c1f8fd6106d9427e1ad6cbcfccd10
\ No newline at end of file
+a845779cd31aec3204a6a9c776bd9c9f7d47dd24
\ No newline at end of file
index df9d877537058127fa9788f16e3260cb5e062d06..f173e23fe300a5dd6206166054fdb2844a9ae50d 100644 (file)
@@ -96,6 +96,7 @@ struct PCache1 {
 struct PgHdr1 {
   sqlite3_pcache_page page;
   unsigned int iKey;             /* Key value (page number) */
+  u8 isPinned;                   /* Page in use, not on the LRU list */
   PgHdr1 *pNext;                 /* Next in hash table chain */
   PCache1 *pCache;               /* Cache that currently owns this page */
   PgHdr1 *pLruNext;              /* Next in LRU list of unpinned pages */
@@ -424,34 +425,32 @@ static int pcache1ResizeHash(PCache1 *p){
 ** LRU list, then this function is a no-op.
 **
 ** The PGroup mutex must be held when this function is called.
-**
-** If pPage is NULL then this routine is a no-op.
 */
 static void pcache1PinPage(PgHdr1 *pPage){
   PCache1 *pCache;
   PGroup *pGroup;
 
-  if( pPage==0 ) return;
+  assert( pPage!=0 );
+  assert( pPage->isPinned==0 );
   pCache = pPage->pCache;
   pGroup = pCache->pGroup;
+  assert( pPage->pLruNext || pPage==pGroup->pLruTail );
+  assert( pPage->pLruPrev || pPage==pGroup->pLruHead );
   assert( sqlite3_mutex_held(pGroup->mutex) );
-  if( pPage->pLruNext || pPage==pGroup->pLruTail ){
-    if( pPage->pLruPrev ){
-      pPage->pLruPrev->pLruNext = pPage->pLruNext;
-    }
-    if( pPage->pLruNext ){
-      pPage->pLruNext->pLruPrev = pPage->pLruPrev;
-    }
-    if( pGroup->pLruHead==pPage ){
-      pGroup->pLruHead = pPage->pLruNext;
-    }
-    if( pGroup->pLruTail==pPage ){
-      pGroup->pLruTail = pPage->pLruPrev;
-    }
-    pPage->pLruNext = 0;
-    pPage->pLruPrev = 0;
-    pPage->pCache->nRecyclable--;
+  if( pPage->pLruPrev ){
+    pPage->pLruPrev->pLruNext = pPage->pLruNext;
+  }else{
+    pGroup->pLruHead = pPage->pLruNext;
+  }
+  if( pPage->pLruNext ){
+    pPage->pLruNext->pLruPrev = pPage->pLruPrev;
+  }else{
+    pGroup->pLruTail = pPage->pLruPrev;
   }
+  pPage->pLruNext = 0;
+  pPage->pLruPrev = 0;
+  pPage->isPinned = 1;
+  pCache->nRecyclable--;
 }
 
 
@@ -483,6 +482,7 @@ static void pcache1EnforceMaxPage(PGroup *pGroup){
   while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
     PgHdr1 *p = pGroup->pLruTail;
     assert( p->pCache->pGroup==pGroup );
+    assert( p->isPinned==0 );
     pcache1PinPage(p);
     pcache1RemoveFromHash(p);
     pcache1FreePage(p);
@@ -510,7 +510,7 @@ static void pcache1TruncateUnsafe(
       if( pPage->iKey>=iLimit ){
         pCache->nPage--;
         *pp = pPage->pNext;
-        pcache1PinPage(pPage);
+        if( !pPage->isPinned ) pcache1PinPage(pPage);
         pcache1FreePage(pPage);
       }else{
         pp = &pPage->pNext;
@@ -733,8 +733,11 @@ static sqlite3_pcache_page *pcache1Fetch(
   }
 
   /* Step 2: Abort if no existing page is found and createFlag is 0 */
-  if( pPage || createFlag==0 ){
-    pcache1PinPage(pPage);
+  if( pPage ){
+    if( !pPage->isPinned ) pcache1PinPage(pPage);
+    goto fetch_out;
+  }
+  if( createFlag==0 ){
     goto fetch_out;
   }
 
@@ -775,6 +778,7 @@ static sqlite3_pcache_page *pcache1Fetch(
   )){
     PCache1 *pOther;
     pPage = pGroup->pLruTail;
+    assert( pPage->isPinned==0 );
     pcache1RemoveFromHash(pPage);
     pcache1PinPage(pPage);
     pOther = pPage->pCache;
@@ -811,6 +815,7 @@ static sqlite3_pcache_page *pcache1Fetch(
     pPage->pCache = pCache;
     pPage->pLruPrev = 0;
     pPage->pLruNext = 0;
+    pPage->isPinned = 1;
     *(void **)pPage->page.pExtra = 0;
     pCache->apHash[h] = pPage;
   }
@@ -846,6 +851,7 @@ static void pcache1Unpin(
   */
   assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
   assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
+  assert( pPage->isPinned==1 );
 
   if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
     pcache1RemoveFromHash(pPage);
@@ -861,6 +867,7 @@ static void pcache1Unpin(
       pGroup->pLruHead = pPage;
     }
     pCache->nRecyclable++;
+    pPage->isPinned = 0;
   }
 
   pcache1LeaveMutex(pCache->pGroup);
@@ -987,6 +994,7 @@ int sqlite3PcacheReleaseMemory(int nReq){
 #ifdef SQLITE_PCACHE_SEPARATE_HEADER
       nFree += sqlite3MemSize(p);
 #endif
+      assert( p->isPinned==0 );
       pcache1PinPage(p);
       pcache1RemoveFromHash(p);
       pcache1FreePage(p);
@@ -1011,6 +1019,7 @@ void sqlite3PcacheStats(
   PgHdr1 *p;
   int nRecyclable = 0;
   for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
+    assert( p->isPinned==0 );
     nRecyclable++;
   }
   *pnCurrent = pcache1.grp.nCurrentPage;