From: drh Date: Wed, 10 Aug 2016 03:35:50 +0000 (+0000) Subject: Try to make pcache1TruncateUnsafe() run faster for the case where iLimit is X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fdebug;p=thirdparty%2Fsqlite.git Try to make pcache1TruncateUnsafe() run faster for the case where iLimit is very close to iMaxKey. FossilOrigin-Name: 9ab53605d562a926c5620cba9dc96a3b812a432f --- diff --git a/manifest b/manifest index 5b8d528389..2365986a09 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sall\stimers\sand\sother\sdebugging\slogs\sexcept\sfor\sthe\sone\stimer\son\npcache1TruncateUnsafe(). -D 2016-08-10T02:54:15.340 +C Try\sto\smake\spcache1TruncateUnsafe()\srun\sfaster\sfor\sthe\scase\swhere\siLimit\sis\nvery\sclose\sto\siMaxKey. +D 2016-08-10T03:35:50.389 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -220,7 +220,7 @@ F src/pager.h d1eee3c3f741be247ce6d82752a178515fc8578b F src/parse.y 5dfead8aed90cb0c7c1115898ee2266804daff45 F src/pcache.c 4121a0571c18581ee9f82f086d5e2030051ebd6a F src/pcache.h 9b559127b83f84ff76d735c8262f04853be0c59a -F src/pcache1.c 938bc830177ccd5198ab07a7522338c8598a00f7 +F src/pcache1.c 04279e6cf595ba3520707886e1f4e3a0b6312cad F src/pragma.c 3f3e959390a10c0131676f0e307acce372777e0f F src/prepare.c 6ef0cf2f9274982988ed6b7cab1be23147e94196 F src/printf.c 090fac0f779c93c8a95089a125339686648835e4 @@ -1207,7 +1207,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 42ce53f648a506d0a5d9c1231eb28c11b4e6b124 -R e064622bb758d47c8c7ad1ed3f41c26c +P 5980e625dbb694dc3b0535e71fd986a6d211e245 +R 2aecde0e663e22b28208114fb4e83a67 U drh -Z 49509f85b3a161b812f3ddad4852a442 +Z 9f57a23eafe4610b0bd9a6ac18d687c6 diff --git a/manifest.uuid b/manifest.uuid index 032f706678..49eb0aec75 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5980e625dbb694dc3b0535e71fd986a6d211e245 \ No newline at end of file +9ab53605d562a926c5620cba9dc96a3b812a432f \ No newline at end of file diff --git a/src/pcache1.c b/src/pcache1.c index 5ae4ad06e3..29fbd11936 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -498,14 +498,32 @@ static void pcache1TruncateUnsafe( PCache1 *pCache, /* The cache to truncate */ unsigned int iLimit /* Drop pages with this pgno or larger */ ){ - TESTONLY( unsigned int nPage = 0; ) /* To assert pCache->nPage is correct */ - unsigned int h; + TESTONLY( int nPage = 0; ) /* To assert pCache->nPage is correct */ + unsigned int h, iStop; START_DEBUG_TIMER; int nFree = 0; assert( sqlite3_mutex_held(pCache->pGroup->mutex) ); - for(h=0; hnHash; h++){ - PgHdr1 **pp = &pCache->apHash[h]; + assert( pCache->iMaxKey >= iLimit ); + assert( pCache->nHash > 0 ); + if( pCache->iMaxKey - iLimit < pCache->nHash/2 ){ + /* If we are just shaving the last few pages off the end of the + ** cache, then there is no point in scanning the entire hash table. + ** Only scan those hash slots that might contain pages that need to + ** be removed. */ + iStop = iLimit % pCache->nHash; + h = pCache->iMaxKey % pCache->nHash; + TESTONLY( nPage = -10; ) /* Disable the pCache->nPage validity check */ + }else{ + /* This is the general case where many pages are being removed. + ** It is necessary to scan the entire hash table */ + iStop = 0; + h = pCache->nHash - 1; + } + for(;;){ + PgHdr1 **pp; PgHdr1 *pPage; + assert( hnHash ); + pp = &pCache->apHash[h]; while( (pPage = *pp)!=0 ){ if( pPage->iKey>=iLimit ){ pCache->nPage--; @@ -515,11 +533,13 @@ static void pcache1TruncateUnsafe( pcache1FreePage(pPage); }else{ pp = &pPage->pNext; - TESTONLY( nPage++; ) + TESTONLY( if( nPage>=0 ) nPage++; ) } } + if( h==iStop ) break; + h = h ? h-1 : pCache->nHash - 1; } - assert( pCache->nPage==nPage ); + assert( nPage<0 || pCache->nPage==(unsigned)nPage ); END_DEBUG_TIMER( DEBUG_TIMER_BIG_TIMEOUT ){ sqlite3_log(SQLITE_NOTICE, "slow pcache1TruncateUnsafe() %lld " @@ -955,7 +975,7 @@ static void pcache1Destroy(sqlite3_pcache *p){ PGroup *pGroup = pCache->pGroup; assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) ); pcache1EnterMutex(pGroup); - pcache1TruncateUnsafe(pCache, 0); + if( pCache->nPage ) pcache1TruncateUnsafe(pCache, 0); assert( pGroup->nMaxPage >= pCache->nMax ); pGroup->nMaxPage -= pCache->nMax; assert( pGroup->nMinPage >= pCache->nMin );