From: drh Date: Fri, 16 Oct 2015 03:34:38 +0000 (+0000) Subject: Whenever two or more OP_Column opcodes on the same cursor occur in succession, X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Freorder-column-opcodes;p=thirdparty%2Fsqlite.git Whenever two or more OP_Column opcodes on the same cursor occur in succession, 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 --- diff --git a/manifest b/manifest index 5cd21de928..8731c7dd88 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 5e41d31178..5ac572c15a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -076be5474df628bbbfd2b645adba30e1e093acd0 \ No newline at end of file +08e8f04d1241db8f190686404874461371ffbeaa \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 2c1a9983e5..b26a95c801 100644 --- a/src/btree.c +++ b/src/btree.c @@ -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; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9c28a9a8c1..336301c722 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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 */ /* diff --git a/src/vdbe.c b/src/vdbe.c index 526d5c24ed..db5cdd8d02 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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) ); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 9fed69127a..f7920b3188 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -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->p2nLabel ); + pOp->p2 = aLabel[-1-pOp->p2]; + } + if( pOp->p2>0 && pOp->p2nOp ){ + 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; inOp; 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->p2nLabel ); - 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) ); } diff --git a/tool/mkopcodeh.tcl b/tool/mkopcodeh.tcl index 4c36f24ba4..2eac312e1c 100644 --- a/tool/mkopcodeh.tcl +++ b/tool/mkopcodeh.tcl @@ -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} {