/ Check-in [ce123b5c]
Login

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

Overview
Comment:Another performance tweak: Split the sqlite3BtreeCursorHasMoved() routine into two with the second routine named sqlite3BtreeCursorRestore(). The first now only reports whether or not the cursor has moved and the second tries to restore the cursor. This allows the sqlite3VdbeCursorMoveto() routine to be refactored to avoid stack pointer movements, for a noticable performance gain.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ce123b5c592556a8cd38b01fcc91ba76231d3098
User & Date: drh 2014-08-22 23:33:03
Context
2014-08-23
17:21
Performance optimization in the applyAffinity() logic inside the VDBE. check-in: 25f2246b user: drh tags: trunk
2014-08-22
23:33
Another performance tweak: Split the sqlite3BtreeCursorHasMoved() routine into two with the second routine named sqlite3BtreeCursorRestore(). The first now only reports whether or not the cursor has moved and the second tries to restore the cursor. This allows the sqlite3VdbeCursorMoveto() routine to be refactored to avoid stack pointer movements, for a noticable performance gain. check-in: ce123b5c user: drh tags: trunk
22:26
Factor the saveAllCursors() routine of btree.c into two separate routines, for a noticable performance improvement. check-in: 3eb08439 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

   758    758   
   759    759   #define restoreCursorPosition(p) \
   760    760     (p->eState>=CURSOR_REQUIRESEEK ? \
   761    761            btreeRestoreCursorPosition(p) : \
   762    762            SQLITE_OK)
   763    763   
   764    764   /*
   765         -** Determine whether or not a cursor has moved from the position it
   766         -** was last placed at.  Cursors can move when the row they are pointing
   767         -** at is deleted out from under them.
   768         -**
   769         -** This routine returns an error code if something goes wrong.  The
   770         -** integer *pHasMoved is set as follows:
   771         -**
   772         -**    0:   The cursor is unchanged
   773         -**    1:   The cursor is still pointing at the same row, but the pointers
   774         -**         returned by sqlite3BtreeKeyFetch() or sqlite3BtreeDataFetch()
   775         -**         might now be invalid because of a balance() or other change to the
   776         -**         b-tree.
   777         -**    2:   The cursor is no longer pointing to the row.  The row might have
   778         -**         been deleted out from under the cursor.
   779         -*/
   780         -int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
   781         -  int rc;
   782         -
   783         -  if( pCur->eState==CURSOR_VALID ){
   784         -    *pHasMoved = 0;
   785         -    return SQLITE_OK;
   786         -  }
          765  +** Determine whether or not a cursor has moved from the position where
          766  +** it was last placed, or has been invalidated for any other reason.
          767  +** Cursors can move when the row they are pointing at is deleted out
          768  +** from under them, for example.  Cursor might also move if a btree
          769  +** is rebalanced.
          770  +**
          771  +** Calling this routine with a NULL cursor pointer returns false.
          772  +**
          773  +** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor
          774  +** back to where it ought to be if this routine returns true.
          775  +*/
          776  +int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
          777  +  return pCur && pCur->eState!=CURSOR_VALID;
          778  +}
          779  +
          780  +/*
          781  +** This routine restores a cursor back to its original position after it
          782  +** has been moved by some outside activity (such as a btree rebalance or
          783  +** a row having been deleted out from under the cursor).  
          784  +**
          785  +** On success, the *pDifferentRow parameter is false if the cursor is left
          786  +** pointing at exactly the same row.  *pDifferntRow is the row the cursor
          787  +** was pointing to has been deleted, forcing the cursor to point to some
          788  +** nearby row.
          789  +**
          790  +** This routine should only be called for a cursor that just returned
          791  +** TRUE from sqlite3BtreeCursorHasMoved().
          792  +*/
          793  +int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
          794  +  int rc;
          795  +
          796  +  assert( pCur!=0 );
          797  +  assert( pCur->eState!=CURSOR_VALID );
   787    798     rc = restoreCursorPosition(pCur);
   788    799     if( rc ){
   789         -    *pHasMoved = 2;
          800  +    *pDifferentRow = 1;
   790    801       return rc;
   791    802     }
   792    803     if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
   793         -    *pHasMoved = 2;
          804  +    *pDifferentRow = 1;
   794    805     }else{
   795         -    *pHasMoved = 1;
          806  +    *pDifferentRow = 0;
   796    807     }
   797    808     return SQLITE_OK;
   798    809   }
   799    810   
   800    811   #ifndef SQLITE_OMIT_AUTOVACUUM
   801    812   /*
   802    813   ** Given a page number of a regular database page, return the page

Changes to src/btree.h.

   165    165   int sqlite3BtreeMovetoUnpacked(
   166    166     BtCursor*,
   167    167     UnpackedRecord *pUnKey,
   168    168     i64 intKey,
   169    169     int bias,
   170    170     int *pRes
   171    171   );
   172         -int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
          172  +int sqlite3BtreeCursorHasMoved(BtCursor*);
          173  +int sqlite3BtreeCursorRestore(BtCursor*, int*);
   173    174   int sqlite3BtreeDelete(BtCursor*);
   174    175   int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
   175    176                                     const void *pData, int nData,
   176    177                                     int nZero, int bias, int seekResult);
   177    178   int sqlite3BtreeFirst(BtCursor*, int *pRes);
   178    179   int sqlite3BtreeLast(BtCursor*, int *pRes);
   179    180   int sqlite3BtreeNext(BtCursor*, int *pRes);

Changes to src/vdbeaux.c.

  2708   2708     if( p->pNext ){
  2709   2709       p->pNext->pPrev = p->pPrev;
  2710   2710     }
  2711   2711     p->magic = VDBE_MAGIC_DEAD;
  2712   2712     p->db = 0;
  2713   2713     sqlite3DbFree(db, p);
  2714   2714   }
         2715  +
         2716  +/*
         2717  +** The cursor "p" has a pending seek operation that has not yet been
         2718  +** carried out.  Seek the cursor now.  If an error occurs, return
         2719  +** the appropriate error code.
         2720  +*/
         2721  +static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
         2722  +  int res, rc;
         2723  +#ifdef SQLITE_TEST
         2724  +  extern int sqlite3_search_count;
         2725  +#endif
         2726  +  assert( p->deferredMoveto );
         2727  +  assert( p->isTable );
         2728  +  rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
         2729  +  if( rc ) return rc;
         2730  +  p->lastRowid = p->movetoTarget;
         2731  +  if( res!=0 ) return SQLITE_CORRUPT_BKPT;
         2732  +  p->rowidIsValid = 1;
         2733  +#ifdef SQLITE_TEST
         2734  +  sqlite3_search_count++;
         2735  +#endif
         2736  +  p->deferredMoveto = 0;
         2737  +  p->cacheStatus = CACHE_STALE;
         2738  +  return SQLITE_OK;
         2739  +}
         2740  +
         2741  +/*
         2742  +** Something has moved cursor "p" out of place.  Maybe the row it was
         2743  +** pointed to was deleted out from under it.  Or maybe the btree was
         2744  +** rebalanced.  Whatever the cause, try to restore "p" to the place it
         2745  +** is suppose to be pointing.  If the row was deleted out from under the
         2746  +** cursor, set the cursor to point to a NULL row.
         2747  +*/
         2748  +static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){
         2749  +  int isDifferentRow, rc;
         2750  +  assert( p->pCursor!=0 );
         2751  +  assert( sqlite3BtreeCursorHasMoved(p->pCursor) );
         2752  +  rc = sqlite3BtreeCursorRestore(p->pCursor, &isDifferentRow);
         2753  +  p->cacheStatus = CACHE_STALE;
         2754  +  if( isDifferentRow ) p->nullRow = 1;
         2755  +  return rc;
         2756  +}
  2715   2757   
  2716   2758   /*
  2717   2759   ** Make sure the cursor p is ready to read or write the row to which it
  2718   2760   ** was last positioned.  Return an error code if an OOM fault or I/O error
  2719   2761   ** prevents us from positioning the cursor to its correct position.
  2720   2762   **
  2721   2763   ** If a MoveTo operation is pending on the given cursor, then do that
................................................................................
  2724   2766   ** a NULL row.
  2725   2767   **
  2726   2768   ** If the cursor is already pointing to the correct row and that row has
  2727   2769   ** not been deleted out from under the cursor, then this routine is a no-op.
  2728   2770   */
  2729   2771   int sqlite3VdbeCursorMoveto(VdbeCursor *p){
  2730   2772     if( p->deferredMoveto ){
  2731         -    int res, rc;
  2732         -#ifdef SQLITE_TEST
  2733         -    extern int sqlite3_search_count;
  2734         -#endif
  2735         -    assert( p->isTable );
  2736         -    rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
  2737         -    if( rc ) return rc;
  2738         -    p->lastRowid = p->movetoTarget;
  2739         -    if( res!=0 ) return SQLITE_CORRUPT_BKPT;
  2740         -    p->rowidIsValid = 1;
  2741         -#ifdef SQLITE_TEST
  2742         -    sqlite3_search_count++;
  2743         -#endif
  2744         -    p->deferredMoveto = 0;
  2745         -    p->cacheStatus = CACHE_STALE;
  2746         -  }else if( p->pCursor ){
  2747         -    int hasMoved;
  2748         -    int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved);
  2749         -    if( rc ) return rc;
  2750         -    if( hasMoved ){
  2751         -      p->cacheStatus = CACHE_STALE;
  2752         -      if( hasMoved==2 ) p->nullRow = 1;
  2753         -    }
         2773  +    return handleDeferredMoveto(p);
         2774  +  }
         2775  +  if( sqlite3BtreeCursorHasMoved(p->pCursor) ){
         2776  +    return handleMovedCursor(p);
  2754   2777     }
  2755   2778     return SQLITE_OK;
  2756   2779   }
  2757   2780   
  2758   2781   /*
  2759   2782   ** The following functions:
  2760   2783   **