]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improve performance in single-threaded mode by having the final merge pass keys direc... threads-experimental
authordan <dan@noemail.net>
Mon, 14 Apr 2014 18:41:21 +0000 (18:41 +0000)
committerdan <dan@noemail.net>
Mon, 14 Apr 2014 18:41:21 +0000 (18:41 +0000)
FossilOrigin-Name: 02610cd9b77caa2c181210056088beb3ad6ce30f

manifest
manifest.uuid
src/vdbesort.c

index eb0882e7ed9b7831fa6f587d0e44b71af0318aec..08cf12e6219f946bf40b8795f31db716e1a9cb85 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Minor\sfixes\sso\sthat\sbuilds\swith\sSQLITE_MAX_WORKER_THREADS=0\swork.
-D 2014-04-14T08:45:32.394
+C Improve\sperformance\sin\ssingle-threaded\smode\sby\shaving\sthe\sfinal\smerge\spass\skeys\sdirectly\sto\sthe\sVDBE,\sinstead\sof\sgoing\svia\sa\sfinal\sPMA.
+D 2014-04-14T18:41:21.894
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in ad0921c4b2780d01868cf69b419a4f102308d125
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -286,7 +286,7 @@ F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4
 F src/vdbeaux.c d8dc38965507a34b0e150c0d7fc82b02f8cf25ea
 F src/vdbeblob.c 15377abfb59251bccedd5a9c7d014a895f0c04aa
 F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
-F src/vdbesort.c 364cb94cf1eaefa1f79d86b7b1e4778c58192e1c
+F src/vdbesort.c 15f59dc56c7c4509b4783ad20fb25479ac63d267
 F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
 F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
 F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
@@ -1163,7 +1163,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P e1bdc4b810907cc0e55e0c923c8ebc777068cfe0
-R 15b762d2cb0315f25703d6fa43b514ac
+P e400bbbf26cdfe88f6cb231e96cdcddb9a6bcc0f
+R b74f7a073d8c77e32a2dce332520aa10
 U dan
-Z 8e0f4aca92a8e556e8d49ca399252be9
+Z cd43207b847b4088208c6c3dd9c99bf8
index bd230a5f991af3ccbcd2e3eea4a67352fdeb6a11..0cd782fad35b2a7db0f4219f31503b4024e8ae4f 100644 (file)
@@ -1 +1 @@
-e400bbbf26cdfe88f6cb231e96cdcddb9a6bcc0f
\ No newline at end of file
+02610cd9b77caa2c181210056088beb3ad6ce30f
\ No newline at end of file
index 870e4e2e1cb9cf3cd4b7deae5863a56eabcf67b4..857b7ba6901f32100eb505430e6df20f2a6a9419 100644 (file)
@@ -280,21 +280,17 @@ struct MergeEngine {
 struct VdbeSorter {
   int mnPmaSize;                  /* Minimum PMA size, in bytes */
   int mxPmaSize;                  /* Maximum PMA size, in bytes.  0==no limit */
-  int bUsePMA;                    /* True if one or more PMAs created */
-  int bUseThreads;                /* True if one or more PMAs created */
   PmaReader *pReader;             /* Read data from here after Rewind() */
+  MergeEngine *pMerger;           /* Or here, if bUseThreads==0 */
   int mxKeysize;                  /* Largest serialized key seen so far */
   UnpackedRecord *pUnpacked;      /* Used by VdbeSorterCompare() */
-#if 0
-  int nInMemory;                  /* Current size of pRecord list as PMA */
-  SorterRecord *pRecord;          /* Head of in-memory record list */
-  u8 *aMemory;                    /* Block of memory to alloc records from */
-#endif
-  SorterList list;
-  int iMemory;                    /* Offset of first free byte in aMemory */
-  int nMemory;                    /* Size of aMemory allocation in bytes */
-  int iPrev;                      /* Previous thread used to flush PMA */
-  int nTask;                      /* Size of aTask[] array */
+  SorterList list;                /* List of in-memory records */
+  int iMemory;                    /* Offset of free space in list.aMemory */
+  int nMemory;                    /* Size of list.aMemory allocation in bytes */
+  u8 bUsePMA;                     /* True if one or more PMAs created */
+  u8 bUseThreads;                 /* True to use background threads */
+  u8 iPrev;                       /* Previous thread used to flush PMA */
+  u8 nTask;                       /* Size of aTask[] array */
   SortSubtask aTask[1];           /* One or more subtasks */
 };
 
@@ -1005,6 +1001,8 @@ void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
     sqlite3DbFree(db, pSorter->pReader);
     pSorter->pReader = 0;
   }
+  vdbeMergeEngineFree(pSorter->pMerger);
+  pSorter->pMerger = 0;
   for(i=0; i<pSorter->nTask; i++){
     SortSubtask *pTask = &pSorter->aTask[i];
     vdbeSortSubtaskCleanup(db, pTask);
@@ -1713,22 +1711,39 @@ static void vdbeIncrSetThreads(IncrMerger *pIncr, int bUseThread){
 #define INCRINIT2_NORMAL 0
 #define INCRINIT2_TASK   1
 #define INCRINIT2_ROOT   2
+
+static int vdbeIncrInit2(PmaReader *pIter, int eMode);
+
+static int vdbeIncrInitMerger(
+  SortSubtask *pTask, 
+  MergeEngine *pMerger, 
+  int eMode
+){
+  int i;
+  int rc = SQLITE_OK;
+
+  for(i=0; rc==SQLITE_OK && i<pMerger->nTree; i++){
+    if( eMode==INCRINIT2_ROOT ){
+      rc = vdbePmaReaderNext(&pMerger->aIter[i]);
+    }else{
+      rc = vdbeIncrInit2(&pMerger->aIter[i], INCRINIT2_NORMAL);
+    }
+  }
+
+  for(i=pMerger->nTree-1; rc==SQLITE_OK && i>0; i--){
+    rc = vdbeSorterDoCompare(pTask, pMerger, i);
+  }
+
+  return rc;
+}
+
 static int vdbeIncrInit2(PmaReader *pIter, int eMode){
   int rc = SQLITE_OK;
   IncrMerger *pIncr = pIter->pIncr;
   if( pIncr ){
     SortSubtask *pTask = pIncr->pTask;
-    int i;
-    MergeEngine *pMerger = pIncr->pMerger;
 
-    for(i=0; rc==SQLITE_OK && i<pMerger->nTree; i++){
-      IncrMerger *p;
-      if( eMode==INCRINIT2_ROOT ){
-        rc = vdbePmaReaderNext(&pMerger->aIter[i]);
-      }else{
-        rc = vdbeIncrInit2(&pMerger->aIter[i], INCRINIT2_NORMAL);
-      }
-    }
+    rc = vdbeIncrInitMerger(pTask, pIncr->pMerger, eMode);
 
     /* Set up the required files for pIncr */
     if( rc==SQLITE_OK ){
@@ -1754,10 +1769,6 @@ static int vdbeIncrInit2(PmaReader *pIter, int eMode){
       }
     }
 
-    for(i=pMerger->nTree-1; rc==SQLITE_OK && i>0; i--){
-      rc = vdbeSorterDoCompare(pIncr->pTask, pMerger, i);
-    }
-
     if( rc==SQLITE_OK && pIncr->bUseThread ){
       /* Use the current thread */
       assert( eMode==INCRINIT2_ROOT || eMode==INCRINIT2_TASK );
@@ -1871,7 +1882,7 @@ static int vdbeAddToBuilder(
 ** Populate iterator *pIter so that it may be used to iterate through all 
 ** keys stored in all PMAs created by this sorter.
 */
-static int vdbePmaReaderIncrInit(VdbeSorter *pSorter, PmaReader *pIter){
+static int vdbePmaReaderIncrInit(VdbeSorter *pSorter){
   SortSubtask *pTask0 = &pSorter->aTask[0];
   MergeEngine *pMain = 0;
   sqlite3 *db = pTask0->db;
@@ -1943,39 +1954,49 @@ static int vdbePmaReaderIncrInit(VdbeSorter *pSorter, PmaReader *pIter){
   }
 
   if( rc==SQLITE_OK ){
-    SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1];
-
-    rc = vdbeSortAllocUnpacked(pLast);
-    if( rc==SQLITE_OK ){
-      pIter->pIncr = vdbeIncrNew(pLast, pMain);
-      if( pIter->pIncr==0 ){
-        rc = SQLITE_NOMEM;
+#if SQLITE_MAX_WORKER_THREADS
+    if( pSorter->bUseThreads ){
+      PmaReader *pIter;
+      SortSubtask *pLast = &pSorter->aTask[pSorter->nTask-1];
+      rc = vdbeSortAllocUnpacked(pLast);
+      if( rc==SQLITE_OK ){
+        pIter = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader));
+        pSorter->pReader = pIter;
       }
-#if SQLITE_MAX_WORKER_THREADS>0
-      else{
-        vdbeIncrSetThreads(pIter->pIncr, pSorter->bUseThreads);
-        for(iTask=0; iTask<(pSorter->nTask-1); iTask++){
-          IncrMerger *pIncr;
-          if( (pIncr = pMain->aIter[iTask].pIncr) ){
-            vdbeIncrSetThreads(pIncr, pSorter->bUseThreads);
-            assert( pIncr->pTask!=pLast );
-          }
+      if( rc==SQLITE_OK ){
+        pIter->pIncr = vdbeIncrNew(pLast, pMain);
+        if( pIter->pIncr==0 ){
+          rc = SQLITE_NOMEM;
         }
-        if( pSorter->nTask>1 ){
-          for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
-            PmaReader *p = &pMain->aIter[iTask];
-            assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] );
-            if( p->pIncr ){ rc = vdbeIncrBgInit2(p); }
+        else{
+          vdbeIncrSetThreads(pIter->pIncr, pSorter->bUseThreads);
+          for(iTask=0; iTask<(pSorter->nTask-1); iTask++){
+            IncrMerger *pIncr;
+            if( (pIncr = pMain->aIter[iTask].pIncr) ){
+              vdbeIncrSetThreads(pIncr, pSorter->bUseThreads);
+              assert( pIncr->pTask!=pLast );
+            }
+          }
+          if( pSorter->nTask>1 ){
+            for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
+              PmaReader *p = &pMain->aIter[iTask];
+              assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] );
+              if( p->pIncr ){ rc = vdbeIncrBgInit2(p); }
+            }
           }
         }
       }
+      if( rc==SQLITE_OK ){
+        int eMode = (pSorter->nTask>1 ? INCRINIT2_ROOT : INCRINIT2_NORMAL);
+        rc = vdbeIncrInit2(pIter, eMode);
+      }
+    }else
 #endif
+    {
+      pSorter->pMerger = pMain;
+      rc = vdbeIncrInitMerger(pTask0, pMain, INCRINIT2_NORMAL);
     }
   }
-  if( rc==SQLITE_OK ){
-    int eMode = (pSorter->nTask>1 ? INCRINIT2_ROOT : INCRINIT2_NORMAL);
-    rc = vdbeIncrInit2(pIter, eMode);
-  }
 
   sqlite3_free(aMerge);
   return rc;
@@ -2020,11 +2041,7 @@ int sqlite3VdbeSorterRewind(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
   ** incrementally read and merge all remaining PMAs.  */
   assert( pSorter->pReader==0 );
   if( rc==SQLITE_OK ){
-    PmaReader *pReader;
-    pReader = (PmaReader*)sqlite3DbMallocZero(db, sizeof(PmaReader));
-    pSorter->pReader = pReader;
-    rc = vdbePmaReaderIncrInit(pSorter, pReader);
-    assert( rc!=SQLITE_OK || pReader->pFile );
+    rc = vdbePmaReaderIncrInit(pSorter);
     *pbEof = 0;
   }
 
@@ -2039,9 +2056,17 @@ int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
   VdbeSorter *pSorter = pCsr->pSorter;
   int rc;                         /* Return code */
 
-  if( pSorter->pReader ){
-    rc = vdbePmaReaderNext(pSorter->pReader);
-    *pbEof = (pSorter->pReader->pFile==0);
+  assert( pSorter->bUsePMA || (pSorter->pReader==0 && pSorter->pMerger==0) );
+  if( pSorter->bUsePMA ){
+    assert( pSorter->pReader==0 || pSorter->pMerger==0 );
+    assert( pSorter->bUseThreads==0 || pSorter->pReader );
+    assert( pSorter->bUseThreads==1 || pSorter->pMerger );
+    if( pSorter->bUseThreads ){
+      rc = vdbePmaReaderNext(pSorter->pReader);
+      *pbEof = (pSorter->pReader->pFile==0);
+    }else{
+      rc = vdbeSorterNext(&pSorter->aTask[0], pSorter->pMerger, pbEof);
+    }
   }else{
     SorterRecord *pFree = pSorter->list.pList;
     pSorter->list.pList = pFree->u.pNext;
@@ -2062,9 +2087,12 @@ static void *vdbeSorterRowkey(
   int *pnKey                      /* OUT: Size of current key in bytes */
 ){
   void *pKey;
-  if( pSorter->pReader ){
-    *pnKey = pSorter->pReader->nKey;
-    pKey = pSorter->pReader->aKey;
+  if( pSorter->bUsePMA ){
+    PmaReader *pReader = (pSorter->bUseThreads ?
+        pSorter->pReader : &pSorter->pMerger->aIter[pSorter->pMerger->aTree[1]]
+    );
+    *pnKey = pReader->nKey;
+    pKey = pReader->aKey;
   }else{
     *pnKey = pSorter->list.pList->nVal;
     pKey = SRVAL(pSorter->list.pList);