From: drh Date: Fri, 9 Sep 2016 19:33:00 +0000 (+0000) Subject: Performance improvements to the comparison operators in the bytecode engine. X-Git-Tag: version-3.15.0~104 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=64caee40865a8edc3d1ea2f86a63859bb2c5cdb5;p=thirdparty%2Fsqlite.git Performance improvements to the comparison operators in the bytecode engine. FossilOrigin-Name: 37803b19d219f4107f29b240d5d314600e4bd236 --- diff --git a/manifest b/manifest index 0c8f1e22eb..e10c5a254b 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 163d453923..da37ec616c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6ac932c92a61cd68cc5b1816216e4748a5c7b3cd \ No newline at end of file +37803b19d219f4107f29b240d5d314600e4bd236 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index c3c9c607cb..91ff5bc900 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 963833cce5..710ce84b97 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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; in && 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; } /*