/ Check-in [1a249845]
Login

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

Overview
Comment:Experimental changes to improve the performance of OP_Next.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1:1a249845251199c00817893add300a1a654b4df9
User & Date: dan 2011-08-27 18:48:57
Context
2011-08-28
00:19
Correctly display P4_ADVANCE values on opcode traces. Mark an always-taken branch in OP_Column as such. check-in: 087dc960 user: drh tags: experimental
2011-08-27
18:48
Experimental changes to improve the performance of OP_Next. check-in: 1a249845 user: dan tags: experimental
2011-08-26
20:55
Fix several harmless compiler warnings and a documentation bug. check-in: 5454d0fe user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  3475   3475     assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
  3476   3476     assert( pBt->pPage1 && pBt->pPage1->aData );
  3477   3477   
  3478   3478     if( NEVER(wrFlag && pBt->readOnly) ){
  3479   3479       return SQLITE_READONLY;
  3480   3480     }
  3481   3481     if( iTable==1 && btreePagecount(pBt)==0 ){
  3482         -    return SQLITE_EMPTY;
         3482  +    assert( wrFlag==0 );
         3483  +    iTable = 0;
  3483   3484     }
  3484   3485   
  3485   3486     /* Now that no other errors can occur, finish filling in the BtCursor
  3486   3487     ** variables and link the cursor into the BtShared list.  */
  3487   3488     pCur->pgnoRoot = (Pgno)iTable;
  3488   3489     pCur->iPage = -1;
  3489   3490     pCur->pKeyInfo = pKeyInfo;
................................................................................
  4229   4230   
  4230   4231     if( pCur->iPage>=0 ){
  4231   4232       int i;
  4232   4233       for(i=1; i<=pCur->iPage; i++){
  4233   4234         releasePage(pCur->apPage[i]);
  4234   4235       }
  4235   4236       pCur->iPage = 0;
         4237  +  }else if( pCur->pgnoRoot==0 ){
         4238  +    pCur->eState = CURSOR_INVALID;
         4239  +    return SQLITE_OK;
  4236   4240     }else{
  4237   4241       rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
  4238   4242       if( rc!=SQLITE_OK ){
  4239   4243         pCur->eState = CURSOR_INVALID;
  4240   4244         return rc;
  4241   4245       }
  4242   4246       pCur->iPage = 0;
................................................................................
  4338   4342     int rc;
  4339   4343   
  4340   4344     assert( cursorHoldsMutex(pCur) );
  4341   4345     assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  4342   4346     rc = moveToRoot(pCur);
  4343   4347     if( rc==SQLITE_OK ){
  4344   4348       if( pCur->eState==CURSOR_INVALID ){
  4345         -      assert( pCur->apPage[pCur->iPage]->nCell==0 );
         4349  +      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
  4346   4350         *pRes = 1;
  4347   4351       }else{
  4348   4352         assert( pCur->apPage[pCur->iPage]->nCell>0 );
  4349   4353         *pRes = 0;
  4350   4354         rc = moveToLeftmost(pCur);
  4351   4355       }
  4352   4356     }
................................................................................
  4377   4381   #endif
  4378   4382       return SQLITE_OK;
  4379   4383     }
  4380   4384   
  4381   4385     rc = moveToRoot(pCur);
  4382   4386     if( rc==SQLITE_OK ){
  4383   4387       if( CURSOR_INVALID==pCur->eState ){
  4384         -      assert( pCur->apPage[pCur->iPage]->nCell==0 );
         4388  +      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
  4385   4389         *pRes = 1;
  4386   4390       }else{
  4387   4391         assert( pCur->eState==CURSOR_VALID );
  4388   4392         *pRes = 0;
  4389   4393         rc = moveToRightmost(pCur);
  4390   4394         pCur->atLast = rc==SQLITE_OK ?1:0;
  4391   4395       }
................................................................................
  4450   4454       }
  4451   4455     }
  4452   4456   
  4453   4457     rc = moveToRoot(pCur);
  4454   4458     if( rc ){
  4455   4459       return rc;
  4456   4460     }
  4457         -  assert( pCur->apPage[pCur->iPage] );
  4458         -  assert( pCur->apPage[pCur->iPage]->isInit );
  4459         -  assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID );
         4461  +  assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
         4462  +  assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
         4463  +  assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
  4460   4464     if( pCur->eState==CURSOR_INVALID ){
  4461   4465       *pRes = -1;
  4462         -    assert( pCur->apPage[pCur->iPage]->nCell==0 );
         4466  +    assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
  4463   4467       return SQLITE_OK;
  4464   4468     }
  4465   4469     assert( pCur->apPage[0]->intKey || pIdxKey );
  4466   4470     for(;;){
  4467   4471       int lwr, upr, idx;
  4468   4472       Pgno chldPg;
  4469   4473       MemPage *pPage = pCur->apPage[pCur->iPage];
................................................................................
  7372   7376   ** SQLITE_OK is returned if the operation is successfully executed. 
  7373   7377   ** Otherwise, if an error is encountered (i.e. an IO error or database
  7374   7378   ** corruption) an SQLite error code is returned.
  7375   7379   */
  7376   7380   int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
  7377   7381     i64 nEntry = 0;                      /* Value to return in *pnEntry */
  7378   7382     int rc;                              /* Return code */
         7383  +
         7384  +  if( pCur->pgnoRoot==0 ){
         7385  +    *pnEntry = 0;
         7386  +    return SQLITE_OK;
         7387  +  }
  7379   7388     rc = moveToRoot(pCur);
  7380   7389   
  7381   7390     /* Unless an error occurs, the following loop runs one iteration for each
  7382   7391     ** page in the B-Tree structure (not including overflow pages). 
  7383   7392     */
  7384   7393     while( rc==SQLITE_OK ){
  7385   7394       int iIdx;                          /* Index of child node in parent */

Changes to src/vdbe.c.

  2546   2546   */
  2547   2547   #ifndef SQLITE_OMIT_BTREECOUNT
  2548   2548   case OP_Count: {         /* out2-prerelease */
  2549   2549     i64 nEntry;
  2550   2550     BtCursor *pCrsr;
  2551   2551   
  2552   2552     pCrsr = p->apCsr[pOp->p1]->pCursor;
  2553         -  if( pCrsr ){
         2553  +  if( ALWAYS(pCrsr) ){
  2554   2554       rc = sqlite3BtreeCount(pCrsr, &nEntry);
  2555   2555     }else{
  2556   2556       nEntry = 0;
  2557   2557     }
  2558   2558     pOut->u.i = nEntry;
  2559   2559     break;
  2560   2560   }
................................................................................
  3108   3108     pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
  3109   3109     if( pCur==0 ) goto no_mem;
  3110   3110     pCur->nullRow = 1;
  3111   3111     pCur->isOrdered = 1;
  3112   3112     rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
  3113   3113     pCur->pKeyInfo = pKeyInfo;
  3114   3114   
  3115         -  /* Since it performs no memory allocation or IO, the only values that
  3116         -  ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK. 
  3117         -  ** SQLITE_EMPTY is only returned when attempting to open the table
  3118         -  ** rooted at page 1 of a zero-byte database.  */
  3119         -  assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
  3120         -  if( rc==SQLITE_EMPTY ){
  3121         -    pCur->pCursor = 0;
  3122         -    rc = SQLITE_OK;
  3123         -  }
         3115  +  /* Since it performs no memory allocation or IO, the only value that
         3116  +  ** sqlite3BtreeCursor() may return is SQLITE_OK. */
         3117  +  assert( rc==SQLITE_OK );
  3124   3118   
  3125   3119     /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
  3126   3120     ** SQLite used to check if the root-page flags were sane at this point
  3127   3121     ** and report database corruption if they were not, but this check has
  3128   3122     ** since moved into the btree layer.  */  
  3129   3123     pCur->isTable = pOp->p4type!=P4_KEYINFO;
  3130   3124     pCur->isIndex = !pCur->isTable;
................................................................................
  3329   3323     pC = p->apCsr[pOp->p1];
  3330   3324     assert( pC!=0 );
  3331   3325     assert( pC->pseudoTableReg==0 );
  3332   3326     assert( OP_SeekLe == OP_SeekLt+1 );
  3333   3327     assert( OP_SeekGe == OP_SeekLt+2 );
  3334   3328     assert( OP_SeekGt == OP_SeekLt+3 );
  3335   3329     assert( pC->isOrdered );
  3336         -  if( pC->pCursor!=0 ){
         3330  +  if( ALWAYS(pC->pCursor!=0) ){
  3337   3331       oc = pOp->opcode;
  3338   3332       pC->nullRow = 0;
  3339   3333       if( pC->isTable ){
  3340   3334         /* The input value in P3 might be of any type: integer, real, string,
  3341   3335         ** blob, or NULL.  But it needs to be an integer before we can do
  3342   3336         ** the seek, so covert it. */
  3343   3337         pIn3 = &aMem[pOp->p3];
................................................................................
  3687   3681     assert( pIn3->flags & MEM_Int );
  3688   3682     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  3689   3683     pC = p->apCsr[pOp->p1];
  3690   3684     assert( pC!=0 );
  3691   3685     assert( pC->isTable );
  3692   3686     assert( pC->pseudoTableReg==0 );
  3693   3687     pCrsr = pC->pCursor;
  3694         -  if( pCrsr!=0 ){
         3688  +  if( ALWAYS(pCrsr!=0) ){
  3695   3689       res = 0;
  3696   3690       iKey = pIn3->u.i;
  3697   3691       rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
  3698   3692       pC->lastRowid = pIn3->u.i;
  3699   3693       pC->rowidIsValid = res==0 ?1:0;
  3700   3694       pC->nullRow = 0;
  3701   3695       pC->cacheStatus = CACHE_STALE;
................................................................................
  4214   4208     VdbeCursor *pC;
  4215   4209   
  4216   4210     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4217   4211     pC = p->apCsr[pOp->p1];
  4218   4212     assert( pC!=0 );
  4219   4213     pC->nullRow = 1;
  4220   4214     pC->rowidIsValid = 0;
         4215  +  assert( pC->pCursor || pC->pVtabCursor );
  4221   4216     if( pC->pCursor ){
  4222   4217       sqlite3BtreeClearCursor(pC->pCursor);
  4223   4218     }
  4224   4219     break;
  4225   4220   }
  4226   4221   
  4227   4222   /* Opcode: Last P1 P2 * * *
................................................................................
  4237   4232     BtCursor *pCrsr;
  4238   4233     int res;
  4239   4234   
  4240   4235     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4241   4236     pC = p->apCsr[pOp->p1];
  4242   4237     assert( pC!=0 );
  4243   4238     pCrsr = pC->pCursor;
  4244         -  if( pCrsr==0 ){
         4239  +  if( NEVER(pCrsr==0) ){
  4245   4240       res = 1;
  4246   4241     }else{
  4247   4242       rc = sqlite3BtreeLast(pCrsr, &res);
  4248   4243     }
  4249   4244     pC->nullRow = (u8)res;
  4250   4245     pC->deferredMoveto = 0;
  4251   4246     pC->rowidIsValid = 0;
................................................................................
  4292   4287   
  4293   4288     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4294   4289     pC = p->apCsr[pOp->p1];
  4295   4290     assert( pC!=0 );
  4296   4291     res = 1;
  4297   4292     if( isSorter(pC) ){
  4298   4293       rc = sqlite3VdbeSorterRewind(db, pC, &res);
  4299         -  }else if( (pCrsr = pC->pCursor)!=0 ){
         4294  +  }else{
         4295  +    pCrsr = pC->pCursor;
         4296  +    assert( pCrsr );
  4300   4297       rc = sqlite3BtreeFirst(pCrsr, &res);
  4301   4298       pC->atFirst = res==0 ?1:0;
  4302   4299       pC->deferredMoveto = 0;
  4303   4300       pC->cacheStatus = CACHE_STALE;
  4304   4301       pC->rowidIsValid = 0;
  4305   4302     }
  4306   4303     pC->nullRow = (u8)res;
................................................................................
  4307   4304     assert( pOp->p2>0 && pOp->p2<p->nOp );
  4308   4305     if( res ){
  4309   4306       pc = pOp->p2 - 1;
  4310   4307     }
  4311   4308     break;
  4312   4309   }
  4313   4310   
  4314         -/* Opcode: Next P1 P2 * * P5
         4311  +/* Opcode: Next P1 P2 * P4 P5
  4315   4312   **
  4316   4313   ** Advance cursor P1 so that it points to the next key/data pair in its
  4317   4314   ** table or index.  If there are no more key/value pairs then fall through
  4318   4315   ** to the following instruction.  But if the cursor advance was successful,
  4319   4316   ** jump immediately to P2.
  4320   4317   **
  4321   4318   ** The P1 cursor must be for a real table, not a pseudo-table.
         4319  +**
         4320  +** P4 is always of type P4_ADVANCE. The function pointer points to
         4321  +** sqlite3BtreeNext().
  4322   4322   **
  4323   4323   ** If P5 is positive and the jump is taken, then event counter
  4324   4324   ** number P5-1 in the prepared statement is incremented.
  4325   4325   **
  4326   4326   ** See also: Prev
  4327   4327   */
  4328   4328   /* Opcode: Prev P1 P2 * * P5
................................................................................
  4329   4329   **
  4330   4330   ** Back up cursor P1 so that it points to the previous key/data pair in its
  4331   4331   ** table or index.  If there is no previous key/value pairs then fall through
  4332   4332   ** to the following instruction.  But if the cursor backup was successful,
  4333   4333   ** jump immediately to P2.
  4334   4334   **
  4335   4335   ** The P1 cursor must be for a real table, not a pseudo-table.
         4336  +**
         4337  +** P4 is always of type P4_ADVANCE. The function pointer points to
         4338  +** sqlite3BtreePrevious().
  4336   4339   **
  4337   4340   ** If P5 is positive and the jump is taken, then event counter
  4338   4341   ** number P5-1 in the prepared statement is incremented.
  4339   4342   */
  4340   4343   case OP_Prev:          /* jump */
  4341   4344   case OP_Next: {        /* jump */
  4342   4345     VdbeCursor *pC;
  4343         -  BtCursor *pCrsr;
  4344   4346     int res;
  4345   4347   
  4346   4348     CHECK_FOR_INTERRUPT;
  4347   4349     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4348   4350     assert( pOp->p5<=ArraySize(p->aCounter) );
  4349   4351     pC = p->apCsr[pOp->p1];
  4350   4352     if( pC==0 ){
  4351   4353       break;  /* See ticket #2273 */
  4352   4354     }
  4353   4355     if( isSorter(pC) ){
  4354   4356       assert( pOp->opcode==OP_Next );
  4355   4357       rc = sqlite3VdbeSorterNext(db, pC, &res);
  4356   4358     }else{
  4357         -    pCrsr = pC->pCursor;
  4358         -    if( pCrsr==0 ){
  4359         -      pC->nullRow = 1;
  4360         -      break;
  4361         -    }
  4362   4359       res = 1;
  4363   4360       assert( pC->deferredMoveto==0 );
  4364         -    rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
  4365         -                                sqlite3BtreePrevious(pCrsr, &res);
         4361  +    assert( pC->pCursor );
         4362  +    assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
         4363  +    assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
         4364  +    rc = pOp->p4.xAdvance(pC->pCursor, &res);
  4366   4365     }
  4367   4366     pC->nullRow = (u8)res;
  4368   4367     pC->cacheStatus = CACHE_STALE;
  4369   4368     if( res==0 ){
  4370   4369       pc = pOp->p2 - 1;
  4371   4370       if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
  4372   4371   #ifdef SQLITE_TEST

Changes to src/vdbe.h.

    57     57       VdbeFunc *pVdbeFunc;   /* Used when p4type is P4_VDBEFUNC */
    58     58       CollSeq *pColl;        /* Used when p4type is P4_COLLSEQ */
    59     59       Mem *pMem;             /* Used when p4type is P4_MEM */
    60     60       VTable *pVtab;         /* Used when p4type is P4_VTAB */
    61     61       KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
    62     62       int *ai;               /* Used when p4type is P4_INTARRAY */
    63     63       SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
           64  +    int (*xAdvance)(BtCursor *, int *);
    64     65     } p4;
    65     66   #ifdef SQLITE_DEBUG
    66     67     char *zComment;          /* Comment to improve readability */
    67     68   #endif
    68     69   #ifdef VDBE_PROFILE
    69     70     int cnt;                 /* Number of times this instruction was executed */
    70     71     u64 cycles;              /* Total time spent executing this instruction */
................................................................................
   112    113   #define P4_VTAB     (-10) /* P4 is a pointer to an sqlite3_vtab structure */
   113    114   #define P4_MPRINTF  (-11) /* P4 is a string obtained from sqlite3_mprintf() */
   114    115   #define P4_REAL     (-12) /* P4 is a 64-bit floating point value */
   115    116   #define P4_INT64    (-13) /* P4 is a 64-bit signed integer */
   116    117   #define P4_INT32    (-14) /* P4 is a 32-bit signed integer */
   117    118   #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
   118    119   #define P4_SUBPROGRAM  (-18) /* P4 is a pointer to a SubProgram structure */
          120  +#define P4_ADVANCE  (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
   119    121   
   120    122   /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
   121    123   ** is made.  That copy is freed when the Vdbe is finalized.  But if the
   122    124   ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used.  It still
   123    125   ** gets freed when the Vdbe is finalized so it still should be obtained
   124    126   ** from a single sqliteMalloc().  But no copy is made and the calling
   125    127   ** function should *not* try to free the KeyInfo.

Changes to src/vdbeaux.c.

   429    429       }else if( opcode==OP_VFilter ){
   430    430         int n;
   431    431         assert( p->nOp - i >= 3 );
   432    432         assert( pOp[-1].opcode==OP_Integer );
   433    433         n = pOp[-1].p1;
   434    434         if( n>nMaxArgs ) nMaxArgs = n;
   435    435   #endif
          436  +    }else if( opcode==OP_Next ){
          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;
   436    442       }
   437    443   
   438    444       if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
   439    445         assert( -1-pOp->p2<p->nLabel );
   440    446         pOp->p2 = aLabel[-1-pOp->p2];
   441    447       }
   442    448     }