]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Whenever two or more OP_Column opcodes on the same cursor occur in succession, reorder-column-opcodes
authordrh <drh@noemail.net>
Fri, 16 Oct 2015 03:34:38 +0000 (03:34 +0000)
committerdrh <drh@noemail.net>
Fri, 16 Oct 2015 03:34:38 +0000 (03:34 +0000)
try to reordering them so that the one that extracts the right-most column is
first, so that it will warm up the row cache for all those that follow.  This
gives a small performance boost.

FossilOrigin-Name: 08e8f04d1241db8f190686404874461371ffbeaa

manifest
manifest.uuid
src/btree.c
src/sqliteInt.h
src/vdbe.c
src/vdbeaux.c
tool/mkopcodeh.tcl

index 5cd21de928024c68a1f932862584ec0a79d639bd..8731c7dd8855c2324ff1b75a43d9ff2bf14f2061 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Performance\soptimization\sfor\sthe\sOP_Column\sopcode.
-D 2015-10-15T21:30:24.579
+C Whenever\stwo\sor\smore\sOP_Column\sopcodes\son\sthe\ssame\scursor\soccur\sin\ssuccession,\ntry\sto\sreordering\sthem\sso\sthat\sthe\sone\sthat\sextracts\sthe\sright-most\scolumn\sis\nfirst,\sso\sthat\sit\swill\swarm\sup\sthe\srow\scache\sfor\sall\sthose\sthat\sfollow.\s\sThis\ngives\sa\ssmall\sperformance\sboost.
+D 2015-10-16T03:34:38.572
 F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 8e42cb55739cd8c12e1fd25401956e2019448f6a
@@ -280,7 +280,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
 F src/backup.c c3a9c4209439b806c44cf30daf466955727bf46c
 F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
 F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
-F src/btree.c 0b74bc28b2dc907cba03b5b4b3b81584273be699
+F src/btree.c ea8c62f65e57e49bd6b0988cd681aca7246b51af
 F src/btree.h 40189aefdc2b830d25c8b58fd7d56538481bfdd7
 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0
 F src/build.c d6162335d690396dfc5c4bd59e8b2b0c14ba6285
@@ -343,7 +343,7 @@ F src/shell.c d25df04168d6ba5a4fa05bdbf859df667f9eb621
 F src/sqlite.h.in 839c818e16ea68703d90d17bd2bb3607191debce
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
 F src/sqlite3ext.h 4b66e3e3435da4b4c8c83696d0349f0c503b3924
-F src/sqliteInt.h 1ad779ee62efee60494af0a75d8d45592f9f53c3
+F src/sqliteInt.h 5332b07164eef1db4a60d2f1301fbb33de71c6d9
 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
 F src/status.c 286f6398a4d2cd1e8ff0771e3d30f8dddb4768ea
 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -401,11 +401,11 @@ F src/update.c aa10336a2719bd1b9f89004f3d7ba6d566623a49
 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
 F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
 F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
-F src/vdbe.c c33faa487c474d41a082979206896988448c9df9
+F src/vdbe.c 32865d7eb6d9241879b1ef62f017abf33811bc2e
 F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
 F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
 F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
-F src/vdbeaux.c fd00b489ab3f44f2dca1e4344faf289b7bfcf649
+F src/vdbeaux.c 170a0eef214941c76f79697640219045e529fcc0
 F src/vdbeblob.c 565fabd302f5fca3bdf3d56cac330483616a39b6
 F src/vdbemem.c 19b3036aa4d676e7103b0fb5efd6327da455f915
 F src/vdbesort.c 8b23930a1289526f6d2a3a9f2e965bcc963e4a68
@@ -1352,7 +1352,7 @@ F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
 F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
 F tool/mkkeywordhash.c dfff09dbbfaf950e89af294f48f902181b144670
 F tool/mkopcodec.tcl edde8adc42621b5e598127f8cdc6d52cfe21f52b
-F tool/mkopcodeh.tcl e04177031532b7aa9379ded50e820231ac4abd6e
+F tool/mkopcodeh.tcl 726340f306e455b478fbe777d71467d220fd3aa5
 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
 F tool/mkpragmatab.tcl 84af2b180484323a2ea22a2279e8bd9e3e1e492e
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1391,7 +1391,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 871e091df651b2275a672c35ff938bd4b6db0d7f
-R 2a9ee0eee7d0527a150149dc10bab0fb
+P 076be5474df628bbbfd2b645adba30e1e093acd0
+R fa3f71993fa566414c3dbec59bd18acc
+T *branch * reorder-column-opcodes
+T *sym-reorder-column-opcodes *
+T -sym-trunk *
 U drh
-Z 586c37c7b737d31273c8670597b9862e
+Z 5fb19142d7f39beb17e045600e97d9ef
index 5e41d31178bd81a8f1dd99573437619dfd570076..5ac572c15a75666632c93200d8673f2b06c6741d 100644 (file)
@@ -1 +1 @@
-076be5474df628bbbfd2b645adba30e1e093acd0
\ No newline at end of file
+08e8f04d1241db8f190686404874461371ffbeaa
\ No newline at end of file
index 2c1a9983e5b4d25bf759e98b7e6e6040371a5155..b26a95c80181fc8242cfdb6b480ca34c412c25cd 100644 (file)
@@ -4499,7 +4499,9 @@ static int accessPayload(
 
       /* If required, populate the overflow page-list cache. */
       if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
-        assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
+        assert( pCur->aOverflow[iIdx]==0
+                || pCur->aOverflow[iIdx]==nextPage
+                || CORRUPT_DB );
         pCur->aOverflow[iIdx] = nextPage;
       }
 
index 9c28a9a8c131020473a88369235bb7ce7511c457..336301c7228c68ed2994e1b13ef9b90d1ad4a050 100644 (file)
@@ -1310,6 +1310,7 @@ struct sqlite3 {
 #define SQLITE_Transitive     0x0200   /* Transitive constraints */
 #define SQLITE_OmitNoopJoin   0x0400   /* Omit unused tables in joins */
 #define SQLITE_Stat34         0x0800   /* Use STAT3 or STAT4 data */
+#define SQLITE_RowCache       0x1000   /* Reorder OP_Column opcodes */
 #define SQLITE_AllOpts        0xffff   /* All optimizations */
 
 /*
index 526d5c24edcaa351606115db51e9872ce9fbbfde..db5cdd8d023238907e41d41c828e127aea8b20e1 100644 (file)
@@ -656,7 +656,7 @@ int sqlite3VdbeExec(
 
     /* Sanity checking on other operands */
 #ifdef SQLITE_DEBUG
-    assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
+    assert( (pOp->opflags&~OPFLG_JMPDEST)==sqlite3OpcodeProperty[pOp->opcode] );
     if( (pOp->opflags & OPFLG_IN1)!=0 ){
       assert( pOp->p1>0 );
       assert( pOp->p1<=(p->nMem-p->nCursor) );
index 9fed69127a707c6a1b6f90f222c61272f20ac494..f7920b3188dad57db133b03433ac1f12306e5952 100644 (file)
@@ -518,21 +518,67 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
 ** (4) Initialize the p4.xAdvance pointer on opcodes that use it.
 **
 ** (5) Reclaim the memory allocated for storing labels.
+**
+** (6) Set the Op.opflags field on all opcodes, and especially the
+**     OPFLG_JMPDEST bit.
+**
+** (7) Reorders OP_Column opcodes against the same cursor so that the
+**     last column is extracted first.  This is a performance optimization.
 */
 static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
-  int i;
+  int i, m;
   int nMaxArgs = *pMaxFuncArgs;
   Op *pOp;
   Parse *pParse = p->pParse;
   int *aLabel = pParse->aLabel;
   p->readOnly = 1;
   p->bIsReader = 0;
+
+  /* First cut at the Op.opcode flags */
   for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
-    u8 opcode = pOp->opcode;
+    pOp->opflags = sqlite3OpcodeProperty[pOp->opcode];
+  }
 
+  /* Resolve goto labels.  And add OPFLG_JMPDEST flags to the
+  ** destinations of jumps. */
+  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
+    if( (pOp->opflags & OPFLG_JUMP)!=0 ){
+      if( pOp->p2<0 ){
+        assert( -1-pOp->p2<pParse->nLabel );
+        pOp->p2 = aLabel[-1-pOp->p2];
+      }
+      if( pOp->p2>0 && pOp->p2<p->nOp ){
+        p->aOp[pOp->p2].opflags |= OPFLG_JMPDEST;
+      }
+    }
+  }
+  sqlite3DbFree(p->db, pParse->aLabel);
+  pParse->aLabel = 0;
+  pParse->nLabel = 0;
+
+  /* Third pass: fix up opcodes */
+  for(pOp=p->aOp, i=m=0; i<p->nOp; i++, pOp++){
     /* NOTE: Be sure to update mkopcodeh.awk when adding or removing
     ** cases from this switch! */
-    switch( opcode ){
+    switch( pOp->opcode ){
+      case OP_Column: {
+        if( OptimizationEnabled(p->db, SQLITE_RowCache) && i>=m ){
+          /* Reorder OP_Column opcodes so that the right-most column is
+          ** extracted first.  This warms up the row cache and helps the
+          ** subsequent OP_Column opcodes to run faster */
+          int j;
+          int b = 0;
+          int p2 = pOp->p2;
+          for(j=1; pOp[j].opcode==OP_Column; j++){
+            if( pOp[j].p1!=pOp->p1 ) break;
+            if( pOp[j].opflags & OPFLG_JMPDEST ) break;
+            if( pOp[j].p2>p2 ){ b = j; p2 = pOp[j].p2; }
+          }
+          if( b ) SWAP(Op, pOp[0], pOp[b]);
+          m = i+j;
+        }
+        break;
+      }
       case OP_Transaction: {
         if( pOp->p2!=0 ) p->readOnly = 0;
         /* fall thru */
@@ -579,16 +625,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
         break;
       }
     }
-
-    pOp->opflags = sqlite3OpcodeProperty[opcode];
-    if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
-      assert( -1-pOp->p2<pParse->nLabel );
-      pOp->p2 = aLabel[-1-pOp->p2];
-    }
   }
-  sqlite3DbFree(p->db, pParse->aLabel);
-  pParse->aLabel = 0;
-  pParse->nLabel = 0;
   *pMaxFuncArgs = nMaxArgs;
   assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
 }
index 4c36f24ba47398e98f8f7efd668bcb877ecf7e26..2eac312e1c4e765c63e189d4da23ae07c6ca02c3 100644 (file)
@@ -126,6 +126,7 @@ incr nOp
 # The following are the opcodes that are processed by resolveP2Values()
 #
 set rp2v_ops {
+  OP_Column
   OP_Transaction
   OP_AutoCommit
   OP_Savepoint
@@ -211,12 +212,13 @@ puts "/* Properties such as \"out2\" or \"jump\" that are specified in"
 puts "** comments following the \"case\" for each opcode in the vdbe.c"
 puts "** are encoded into bitvectors as follows:"
 puts "*/"
-puts "#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */"
-puts "#define OPFLG_IN1             0x0002  /* in1:   P1 is an input */"
-puts "#define OPFLG_IN2             0x0004  /* in2:   P2 is an input */"
-puts "#define OPFLG_IN3             0x0008  /* in3:   P3 is an input */"
-puts "#define OPFLG_OUT2            0x0010  /* out2:  P2 is an output */"
-puts "#define OPFLG_OUT3            0x0020  /* out3:  P3 is an output */"
+puts "#define OPFLG_JUMP            0x01  /* jump:  P2 holds jmp target */"
+puts "#define OPFLG_IN1             0x02  /* in1:   P1 is an input */"
+puts "#define OPFLG_IN2             0x04  /* in2:   P2 is an input */"
+puts "#define OPFLG_IN3             0x08  /* in3:   P3 is an input */"
+puts "#define OPFLG_OUT2            0x10  /* out2:  P2 is an output */"
+puts "#define OPFLG_OUT3            0x20  /* out3:  P3 is an output */"
+puts "#define OPFLG_JMPDEST         0x40  /* A jump destination */"
 puts "#define OPFLG_INITIALIZER \173\\"
 for {set i 0} {$i<=$max} {incr i} {
   if {$i%8==0} {