From: dan Date: Thu, 26 Mar 2015 11:55:03 +0000 (+0000) Subject: Optimize cases where all the sorter is sorting a set of records that all begin with... X-Git-Tag: version-3.8.10~152^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=57a140946f6f7508e64d91b5ae8671f3cab073a0;p=thirdparty%2Fsqlite.git Optimize cases where all the sorter is sorting a set of records that all begin with integer values, or that all begin with text values to be compared using BINARY. FossilOrigin-Name: ce5ad17c25cf2f8274ce304c51e4421faae0b32b --- diff --git a/manifest b/manifest index 6fdfb0ad40..65ccebc2d0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\san\sunreachable\sbranch\sinto\san\sassert(). -D 2015-03-25T18:29:10.982 +C Optimize\scases\swhere\sall\sthe\ssorter\sis\ssorting\sa\sset\sof\srecords\sthat\sall\sbegin\swith\sinteger\svalues,\sor\sthat\sall\sbegin\swith\stext\svalues\sto\sbe\scompared\susing\sBINARY. +D 2015-03-26T11:55:03.488 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -300,7 +300,7 @@ F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 F src/vdbeaux.c 413dc496248ac18eb0c19e35e86bb1ffd47b8907 F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90 F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9 -F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6 +F src/vdbesort.c a8d82ed4b09f3b1f5390c7546a9bcad72d483abf F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010 F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1 F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb @@ -1247,7 +1247,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 37866b4d483296ab9b7fcb9f5486695d4c2b8ddd -R 6f3611ab9d4988693f727ae20dc9c9e5 -U drh -Z 3f028f44e21ab0b1619e9687cba7cf7a +P fb076b28c36975ff2e41440f22fe5de115c195da +R 1e1c6c1ab8dfb515d00c85e16ae436f0 +T *branch * sorter-opt +T *sym-sorter-opt * +T -sym-trunk * +U dan +Z 9752268c90db4ae1847219cb63314e99 diff --git a/manifest.uuid b/manifest.uuid index 849f782137..dfa9f94353 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fb076b28c36975ff2e41440f22fe5de115c195da \ No newline at end of file +ce5ad17c25cf2f8274ce304c51e4421faae0b32b \ No newline at end of file diff --git a/src/vdbesort.c b/src/vdbesort.c index bbdafa8230..4faeebf963 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -298,6 +298,7 @@ struct SortSubtask { UnpackedRecord *pUnpacked; /* Space to unpack a record */ SorterList list; /* List for thread to write to a PMA */ int nPMA; /* Number of PMAs currently in file */ + RecordCompare xCompare; /* Compare function to use */ SorterFile file; /* Temp file for level-0 PMAs */ SorterFile file2; /* Space for other PMAs */ }; @@ -328,9 +329,13 @@ struct VdbeSorter { u8 bUseThreads; /* True to use background threads */ u8 iPrev; /* Previous thread used to flush PMA */ u8 nTask; /* Size of aTask[] array */ + u8 typeMask; SortSubtask aTask[1]; /* One or more subtasks */ }; +#define SORTER_TYPE_INTEGER 0x01 +#define SORTER_TYPE_TEXT 0x02 + /* ** An instance of the following object is used to read records out of a ** PMA, in sorted order. The next key to be read is cached in nKey/aKey. @@ -765,7 +770,7 @@ static int vdbeSorterCompare( if( pKey2 ){ sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2); } - return sqlite3VdbeRecordCompare(nKey1, pKey1, r2); + return pTask->xCompare(nKey1, pKey1, r2); } /* @@ -835,9 +840,13 @@ int sqlite3VdbeSorterInit( pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz); memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo); pKeyInfo->db = 0; - if( nField && nWorker==0 ) pKeyInfo->nField = nField; + if( nField && nWorker==0 ){ + pKeyInfo->nXField += (pKeyInfo->nField - nField); + pKeyInfo->nField = nField; + } pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt); pSorter->nTask = nWorker + 1; + pSorter->iPrev = nWorker-1; pSorter->bUseThreads = (pSorter->nTask>1); pSorter->db = db; for(i=0; inTask; i++){ @@ -863,6 +872,10 @@ int sqlite3VdbeSorterInit( if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM; } } + + if( (pKeyInfo->nField+pKeyInfo->nXField)<13 && pKeyInfo->aColl[0]==0 ){ + pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; + } } return rc; @@ -1182,6 +1195,13 @@ static int vdbeSortAllocUnpacked(SortSubtask *pTask){ if( pFree==0 ) return SQLITE_NOMEM; pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField; pTask->pUnpacked->errCode = 0; + if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + pTask->pUnpacked->r1 = 1; + pTask->pUnpacked->r2 = -1; + }else{ + pTask->pUnpacked->r1 = -1; + pTask->pUnpacked->r2 = 1; + } } return SQLITE_OK; } @@ -1235,12 +1255,20 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){ rc = vdbeSortAllocUnpacked(pTask); if( rc!=SQLITE_OK ) return rc; + p = pList->pList; + if( pTask->pSorter->typeMask==0 ){ + pTask->xCompare = sqlite3VdbeRecordCompare; + }else{ + UnpackedRecord *pRec = pTask->pUnpacked; + sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, p->nVal, SRVAL(p), pRec); + pTask->xCompare = sqlite3VdbeFindCompare(pRec); + } + aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *)); if( !aSlot ){ return SQLITE_NOMEM; } - p = pList->pList; while( p ){ SorterRecord *pNext; if( pList->aMemory ){ @@ -1602,6 +1630,16 @@ int sqlite3VdbeSorterWrite( int bFlush; /* True to flush contents of memory to PMA */ int nReq; /* Bytes of memory required */ int nPMA; /* Bytes of PMA space required */ + int t; /* serial type of first record field */ + + getVarint32((const u8*)&pVal->z[1], t); + if( t>0 && t<10 && t!=7 ){ + pSorter->typeMask &= SORTER_TYPE_INTEGER; + }else if( t & 0x01 ){ + pSorter->typeMask &= SORTER_TYPE_TEXT; + }else{ + pSorter->typeMask = 0; + } assert( pSorter ); @@ -2288,6 +2326,13 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){ MergeEngine *pMain = 0; #if SQLITE_MAX_WORKER_THREADS sqlite3 *db = pTask0->pSorter->db; + RecordCompare xCompare = (pSorter->typeMask==0 ? + sqlite3VdbeRecordCompare : pSorter->aTask[0].xCompare + ); + int i; + for(i=0; inTask; i++){ + pSorter->aTask[i].xCompare = xCompare; + } #endif rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);