]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Performance improvements to the comparison operators in the bytecode engine.
authordrh <drh@noemail.net>
Fri, 9 Sep 2016 19:33:00 +0000 (19:33 +0000)
committerdrh <drh@noemail.net>
Fri, 9 Sep 2016 19:33:00 +0000 (19:33 +0000)
FossilOrigin-Name: 37803b19d219f4107f29b240d5d314600e4bd236

manifest
manifest.uuid
src/vdbe.c
src/vdbeaux.c

index 0c8f1e22ebbf38434f033efc9b53e3a2e054092c..e10c5a254bea043fba3fa03089f76bf2fcfce1f1 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sout-of-order\svariable\sdeclaration\sfor\ssome\scompile-time\sconfigurations.
-D 2016-09-09T15:12:41.801
+C Performance\simprovements\sto\sthe\scomparison\soperators\sin\sthe\sbytecode\sengine.
+D 2016-09-09T19:33:00.624
 F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 5017381e4853b1472e01d5bb926be1268eba429c
@@ -452,11 +452,11 @@ F src/update.c 8179e699dbd45b92934fd02d3d8e3732e8da8802
 F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
 F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d
 F src/vacuum.c 913970b9d86dd6c2b8063ef1af421880f1464ec3
-F src/vdbe.c 3148d5d47816c5ad2ed3c62beb3086cbbcaab107
+F src/vdbe.c 2087dfd6f013a9c808c92f8713fd8c7c62be2857
 F src/vdbe.h 67bc551f7faf04c33493892e4b378aada823ed10
 F src/vdbeInt.h c59381049af5c7751a83456c39b80d1a6fde1f9d
 F src/vdbeapi.c a32d61b7dd05e6890d8fd44d2805f55e2f5ba9f3
-F src/vdbeaux.c 83458783d241cfd6691141c8a105832ee50258e5
+F src/vdbeaux.c 230b6826656144bcdca6d9c09d38da9d927739be
 F src/vdbeblob.c 3e82a797b60c3b9fed7b8de8c539ca7607874937
 F src/vdbemem.c e67dc6d8177fd1830efb5d15e17793408251a187
 F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c
@@ -1523,7 +1523,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 2bdd838e2c434f1d26b1836ef39fa938ef93131d
-R cdaf391119a3a76bb49bf405a13f8694
+P 6ac932c92a61cd68cc5b1816216e4748a5c7b3cd
+R f1fdb6c44ee59a1a70f4ca210b22ee73
 U drh
-Z f913482662ff429e344c363b85d81ce9
+Z 14efbbb4d9b59bda04ac0672b03a8c5e
index 163d453923b615d227b02ce3559dac82a110e44d..da37ec616c7f5e2b2b86ffc61509a8a224196fea 100644 (file)
@@ -1 +1 @@
-6ac932c92a61cd68cc5b1816216e4748a5c7b3cd
\ No newline at end of file
+37803b19d219f4107f29b240d5d314600e4bd236
\ No newline at end of file
index c3c9c607cb46649e1d32dc660a286e9743816782..91ff5bc9004dbedbec1581bf7d23a59d657a1246 100644 (file)
@@ -2035,12 +2035,21 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
       if( (flags1 | flags3)&MEM_Str ){
         if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
           applyNumericAffinity(pIn1,0);
+          testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */
           flags3 = pIn3->flags;
         }
         if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
           applyNumericAffinity(pIn3,0);
         }
       }
+      /* Handle the common case of integer comparison here, as an
+      ** optimization, to avoid a call to sqlite3MemCompare() */
+      if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
+        if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
+        if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
+        res = 0;
+        goto compare_op;
+      }
     }else if( affinity==SQLITE_AFF_TEXT ){
       if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
         testcase( pIn1->flags & MEM_Int );
@@ -2048,6 +2057,7 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
         sqlite3VdbeMemStringify(pIn1, encoding, 1);
         testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
         flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
+        testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */
         flags3 = pIn3->flags;
       }
       if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
@@ -2059,16 +2069,9 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
       }
     }
     assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
-    if( flags1 & MEM_Zero ){
-      sqlite3VdbeMemExpandBlob(pIn1);
-      flags1 &= ~MEM_Zero;
-    }
-    if( flags3 & MEM_Zero ){
-      sqlite3VdbeMemExpandBlob(pIn3);
-      flags3 &= ~MEM_Zero;
-    }
     res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
   }
+compare_op:
   switch( pOp->opcode ){
     case OP_Eq:    res2 = res==0;     break;
     case OP_Ne:    res2 = res;        break;
index 963833cce5ee4bb9a6a6654e2caadfd6ea8db190..710ce84b9728ed6ded13d0bc2e9a08724519a48a 100644 (file)
@@ -3716,15 +3716,47 @@ static int vdbeCompareMemString(
   }
 }
 
+/*
+** The input pBlob is guaranteed to be a Blob that is not marked
+** with MEM_Zero.  Return true if it could be a zero-blob.
+*/
+static int isZeroBlob(const Mem *pBlob){
+  int i;
+  for(i=0; i<pBlob->n && pBlob->z[i]==0; i++){}
+  return i==pBlob->n;
+}
+
 /*
 ** Compare two blobs.  Return negative, zero, or positive if the first
 ** is less than, equal to, or greater than the second, respectively.
 ** If one blob is a prefix of the other, then the shorter is the lessor.
 */
 static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
-  int c = memcmp(pB1->z, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n);
+  int c;
+  int n1 = pB1->n;
+  int n2 = pB2->n;
+
+  /* It is possible to have a Blob value that has some non-zero content
+  ** followed by zero content.  But that only comes up for Blobs formed
+  ** by the OP_MakeRecord opcode, and such Blobs never get passed into
+  ** sqlite3MemCompare(). */
+  assert( (pB1->flags & MEM_Zero)==0 || n1==0 );
+  assert( (pB2->flags & MEM_Zero)==0 || n2==0 );
+
+  if( (pB1->flags|pB2->flags) & MEM_Zero ){
+    if( pB1->flags & pB2->flags & MEM_Zero ){
+      return pB1->u.nZero - pB2->u.nZero;
+    }else if( pB1->flags & MEM_Zero ){
+      if( !isZeroBlob(pB2) ) return -1;
+      return pB1->u.nZero - n2;
+    }else{
+      if( !isZeroBlob(pB1) ) return +1;
+      return n1 - pB2->u.nZero;
+    }
+  }
+  c = memcmp(pB1->z, pB2->z, n1>n2 ? n2 : n1);
   if( c ) return c;
-  return pB1->n - pB2->n;
+  return n1 - n2;
 }
 
 /*