/ Check-in [924f7e4d]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:More than double the speed of the resolveP2Values() routine in vdbeaux.c by moving from an extended if-else on every opcode to a switch. Opcodes are reordered in mkopcodesh.awk to put the switched opcodes close together, for additional performance and to reduce code footprint.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 924f7e4d7a8fa2fe9100836663f3733b6e1a9084
User & Date: drh 2013-08-06 07:45:08
Context
2013-08-06
14:01
Clean up the input reader in the command-line shell for improved legibility and performance. check-in: 2b1743d6 user: drh tags: trunk
07:45
More than double the speed of the resolveP2Values() routine in vdbeaux.c by moving from an extended if-else on every opcode to a switch. Opcodes are reordered in mkopcodesh.awk to put the switched opcodes close together, for additional performance and to reduce code footprint. check-in: 924f7e4d user: drh tags: trunk
2013-08-05
22:05
Performance optimization: Avoid calling convertCompoundSelecctToSubquery() on queries that do not use the UNION, EXCEPT, or INTERSECT operators. check-in: c589b2fe user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to mkopcodeh.awk.

    31     31   # properties apply to that opcode.  Set corresponding flags using the
    32     32   # OPFLG_INITIALIZER macro.
    33     33   #
    34     34   
    35     35   
    36     36   # Remember the TK_ values from the parse.h file
    37     37   /^#define TK_/ {
    38         -  tk[$2] = 0+$3
           38  +  tk[$2] = 0+$3    # tk[x] holds the numeric value for TK symbol X
    39     39   }
    40     40   
    41     41   # Scan for "case OP_aaaa:" lines in the vdbe.c file
    42     42   /^case OP_/ {
    43     43     name = $2
    44     44     sub(/:/,"",name)
    45     45     sub("\r","",name)
    46         -  op[name] = -1
           46  +  op[name] = -1       # op[x] holds the numeric value for OP symbol x
    47     47     jump[name] = 0
    48     48     out2_prerelease[name] = 0
    49     49     in1[name] = 0
    50     50     in2[name] = 0
    51     51     in3[name] = 0
    52     52     out2[name] = 0
    53     53     out3[name] = 0
    54     54     for(i=3; i<NF; i++){
    55     55       if($i=="same" && $(i+1)=="as"){
    56     56         sym = $(i+2)
    57     57         sub(/,/,"",sym)
    58         -      op[name] = tk[sym]
    59         -      used[op[name]] = 1
    60         -      sameas[op[name]] = sym
           58  +      val = tk[sym]
           59  +      op[name] = val
           60  +      used[val] = 1
           61  +      sameas[val] = sym
           62  +      def[val] = name
    61     63       }
    62     64       x = $i
    63     65       sub(",","",x)
    64     66       if(x=="jump"){
    65     67         jump[name] = 1
    66     68       }else if(x=="out2-prerelease"){
    67     69         out2_prerelease[name] = 1
................................................................................
    86     88     max = 0
    87     89     print "/* Automatically generated.  Do not edit */"
    88     90     print "/* See the mkopcodeh.awk script for details */"
    89     91     op["OP_Noop"] = -1;
    90     92     order[n_op++] = "OP_Noop";
    91     93     op["OP_Explain"] = -1;
    92     94     order[n_op++] = "OP_Explain";
           95  +
           96  +  # Assign small values to opcodes that are processed by resolveP2Values()
           97  +  # to make code generation for the switch() statement smaller and faster.
           98  +  for(i=0; i<n_op; i++){
           99  +    name = order[i];
          100  +    if( op[name]>=0 ) continue;
          101  +    if( name=="OP_Function"      \
          102  +     || name=="OP_AggStep"       \
          103  +     || name=="OP_Transaction"   \
          104  +     || name=="OP_AutoCommit"    \
          105  +     || name=="OP_Savepoint"     \
          106  +     || name=="OP_Checkpoint"    \
          107  +     || name=="OP_Vacuum"        \
          108  +     || name=="OP_JournalMode"   \
          109  +     || name=="OP_VUpdate"       \
          110  +     || name=="OP_VFilter"       \
          111  +     || name=="OP_Next"          \
          112  +     || name=="OP_SorterNext"    \
          113  +     || name=="OP_Prev"          \
          114  +    ){
          115  +      cnt++
          116  +      while( used[cnt] ) cnt++
          117  +      op[name] = cnt
          118  +      used[cnt] = 1
          119  +      def[cnt] = name
          120  +    }
          121  +  }
          122  +
          123  +  # Generate the numeric values for opcodes
    93    124     for(i=0; i<n_op; i++){
    94    125       name = order[i];
    95    126       if( op[name]<0 ){
    96    127         cnt++
    97    128         while( used[cnt] ) cnt++
    98    129         op[name] = cnt
          130  +      used[cnt] = 1
          131  +      def[cnt] = name
          132  +    }
          133  +  }
          134  +  max = cnt
          135  +  for(i=1; i<=max; i++){
          136  +    if( !used[i] ){
          137  +      def[i] = "OP_NotUsed_" i 
    99    138       }
   100         -    used[op[name]] = 1;
   101         -    if( op[name]>max ) max = op[name]
   102         -    printf "#define %-25s %15d", name, op[name]
   103         -    if( sameas[op[name]] ) {
   104         -      printf "   /* same as %-12s*/", sameas[op[name]]
          139  +    printf "#define %-25s %15d", def[i], i
          140  +    if( sameas[i] ){
          141  +      printf "   /* same as %-12s*/", sameas[i]
   105    142       } 
   106    143       printf "\n"
   107         -
   108         -  }
   109         -  seenUnused = 0;
   110         -  for(i=1; i<max; i++){
   111         -    if( !used[i] ){
   112         -      if( !seenUnused ){
   113         -        printf "\n/* The following opcode values are never used */\n"
   114         -        seenUnused = 1
   115         -      }
   116         -      printf "#define %-25s %15d\n", sprintf( "OP_NotUsed_%-3d", i ), i
   117         -    }
   118    144     }
   119    145   
   120    146     # Generate the bitvectors:
   121    147     #
   122    148     #  bit 0:     jump
   123    149     #  bit 1:     pushes a result onto stack
   124    150     #  bit 2:     output to p1.  release p1 before opcode runs
   125    151     #
   126         -  for(i=0; i<=max; i++) bv[i] = 0;
   127         -  for(i=0; i<n_op; i++){
   128         -    name = order[i];
   129         -    x = op[name]
          152  +  for(i=0; i<=max; i++){
          153  +    name = def[i]
   130    154       a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
   131         -    # a7 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0
   132    155       if( jump[name] ) a0 = 1;
   133    156       if( out2_prerelease[name] ) a1 = 2;
   134    157       if( in1[name] ) a2 = 4;
   135    158       if( in2[name] ) a3 = 8;
   136    159       if( in3[name] ) a4 = 16;
   137    160       if( out2[name] ) a5 = 32;
   138    161       if( out3[name] ) a6 = 64;
   139         -    # bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15;
   140         -    bv[x] = a0+a1+a2+a3+a4+a5+a6+a7;
          162  +    bv[i] = a0+a1+a2+a3+a4+a5+a6+a7;
   141    163     }
   142    164     print "\n"
   143    165     print "/* Properties such as \"out2\" or \"jump\" that are specified in"
   144    166     print "** comments following the \"case\" for each opcode in the vdbe.c"
   145    167     print "** are encoded into bitvectors as follows:"
   146    168     print "*/"
   147    169     print "#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */"

Changes to src/vdbeaux.c.

   403    403     Op *pOp;
   404    404     int *aLabel = p->aLabel;
   405    405     p->readOnly = 1;
   406    406     p->bIsReader = 0;
   407    407     for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
   408    408       u8 opcode = pOp->opcode;
   409    409   
   410         -    pOp->opflags = sqlite3OpcodeProperty[opcode];
   411         -    if( opcode==OP_Function || opcode==OP_AggStep ){
   412         -      if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
   413         -    }else if( opcode==OP_Transaction ){
   414         -      if( pOp->p2!=0 ) p->readOnly = 0;
   415         -      p->bIsReader = 1;
   416         -    }else if( opcode==OP_AutoCommit || opcode==OP_Savepoint ){
   417         -      p->bIsReader = 1;
   418         -    }else if( opcode==OP_Vacuum
   419         -           || opcode==OP_JournalMode
          410  +    /* NOTE: Be sure to update mkopcodeh.awk when adding or removing
          411  +    ** cases from this switch! */
          412  +    switch( opcode ){
          413  +      case OP_Function:
          414  +      case OP_AggStep: {
          415  +        if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
          416  +        break;
          417  +      }
          418  +      case OP_Transaction: {
          419  +        if( pOp->p2!=0 ) p->readOnly = 0;
          420  +        /* fall thru */
          421  +      }
          422  +      case OP_AutoCommit:
          423  +      case OP_Savepoint: {
          424  +        p->bIsReader = 1;
          425  +        break;
          426  +      }
   420    427   #ifndef SQLITE_OMIT_WAL
   421         -           || opcode==OP_Checkpoint
          428  +      case OP_Checkpoint:
   422    429   #endif
   423         -    ){
   424         -      p->readOnly = 0;
   425         -      p->bIsReader = 1;
          430  +      case OP_Vacuum:
          431  +      case OP_JournalMode: {
          432  +        p->readOnly = 0;
          433  +        p->bIsReader = 1;
          434  +        break;
          435  +      }
   426    436   #ifndef SQLITE_OMIT_VIRTUALTABLE
   427         -    }else if( opcode==OP_VUpdate ){
   428         -      if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
   429         -    }else if( opcode==OP_VFilter ){
   430         -      int n;
   431         -      assert( p->nOp - i >= 3 );
   432         -      assert( pOp[-1].opcode==OP_Integer );
   433         -      n = pOp[-1].p1;
   434         -      if( n>nMaxArgs ) nMaxArgs = n;
   435         -#endif
   436         -    }else if( opcode==OP_Next || opcode==OP_SorterNext ){
   437         -      pOp->p4.xAdvance = sqlite3BtreeNext;
   438         -      pOp->p4type = P4_ADVANCE;
   439         -    }else if( opcode==OP_Prev ){
   440         -      pOp->p4.xAdvance = sqlite3BtreePrevious;
   441         -      pOp->p4type = P4_ADVANCE;
   442         -    }
   443         -
          437  +      case OP_VUpdate: {
          438  +        if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
          439  +        break;
          440  +      }
          441  +      case OP_VFilter: {
          442  +        int n;
          443  +        assert( p->nOp - i >= 3 );
          444  +        assert( pOp[-1].opcode==OP_Integer );
          445  +        n = pOp[-1].p1;
          446  +        if( n>nMaxArgs ) nMaxArgs = n;
          447  +        break;
          448  +      }
          449  +#endif
          450  +      case OP_Next:
          451  +      case OP_SorterNext: {
          452  +        pOp->p4.xAdvance = sqlite3BtreeNext;
          453  +        pOp->p4type = P4_ADVANCE;
          454  +        break;
          455  +      }
          456  +      case OP_Prev: {
          457  +        pOp->p4.xAdvance = sqlite3BtreePrevious;
          458  +        pOp->p4type = P4_ADVANCE;
          459  +        break;
          460  +      }
          461  +    }
          462  +
          463  +    pOp->opflags = sqlite3OpcodeProperty[opcode];
   444    464       if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
   445    465         assert( -1-pOp->p2<p->nLabel );
   446    466         pOp->p2 = aLabel[-1-pOp->p2];
   447    467       }
   448    468     }
   449    469     sqlite3DbFree(p->db, p->aLabel);
   450    470     p->aLabel = 0;