]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove the VdbeCursor.lastRowid cache of the current rowid, since maintaining
authordrh <drh@noemail.net>
Sun, 12 Oct 2014 22:37:22 +0000 (22:37 +0000)
committerdrh <drh@noemail.net>
Sun, 12 Oct 2014 22:37:22 +0000 (22:37 +0000)
the correct cache value uses more CPU cycles than just recomputing the rowid
on the occasions when it is actually needed.  Replace it with the
VdbeCursor.aOffset field which used to be computed from VdbeCursor.aType
when needed. Saves 100 bytes of code space and runs 0.2% faster.

FossilOrigin-Name: 91384a7d727ef0f285cd430e829ba9f3852db50e

manifest
manifest.uuid
src/vdbe.c
src/vdbeInt.h
src/vdbeaux.c

index 62b5d0c87020956816c94ee50cdabb3baccfb2d7..0d0dc6d2490408956a1c972231b69f0b8598faba 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Performance\soptimization\sand\svery\sslight\ssize\sreduction\sfor\sOP_Column.
-D 2014-10-11T23:31:52.159
+C Remove\sthe\sVdbeCursor.lastRowid\scache\sof\sthe\scurrent\srowid,\ssince\smaintaining\nthe\scorrect\scache\svalue\suses\smore\sCPU\scycles\sthan\sjust\srecomputing\sthe\srowid\non\sthe\soccasions\swhen\sit\sis\sactually\sneeded.\s\sReplace\sit\swith\sthe\nVdbeCursor.aOffset\sfield\swhich\sused\sto\sbe\scomputed\sfrom\sVdbeCursor.aType\nwhen\sneeded.\sSaves\s100\sbytes\sof\scode\sspace\sand\sruns\s0.2%\sfaster.
+D 2014-10-12T22:37:22.384
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -289,11 +289,11 @@ F src/update.c 729f6f18fc27740591d085e1172cebe311144bf0
 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
 F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8
 F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a
-F src/vdbe.c 58c19340f009d29b63d3701bd1871aad03e4c134
+F src/vdbe.c 97c6c50e272ed531bc3af308d5f156cfca0ce4f4
 F src/vdbe.h 09f5b4e3719fa454f252322b1cdab5cf1f361327
-F src/vdbeInt.h 0b97a3190f8fbf460655985a9183019f5a702754
+F src/vdbeInt.h e1173bd72b282633c2ec8f3a2f78b5117229f268
 F src/vdbeapi.c 37a6c6ae284a97bcace365f2f0a225680c0499d9
-F src/vdbeaux.c 5b687d7b5beaaa5b97189edf25cf08c311834933
+F src/vdbeaux.c e223d15ab39c844c04ad19931e8c71966c20c68d
 F src/vdbeblob.c 848238dc73e93e48432991bb5651bf87d865eca4
 F src/vdbemem.c 481327f50d9da330053aa7456702ce46d0a4e70f
 F src/vdbesort.c 5c1bacf90578d22b630fbf6ed98ccf60d83435ef
@@ -1204,7 +1204,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 66de15580d3c289601e67debfe1edee286f4db5f
-R 512122d0d240ac7f0b4d899edd214ecb
+P 869c30e45cc87063be423c650f16b99e8adb3df0
+R d569318d3e6a6b025c49ffecae9bf7d4
 U drh
-Z 7a9b66d8d53ebbf7b4743296d025a097
+Z e6cf351e034f82bffef92232dfc65ffe
index 2c31982904843da7c346c72565a7c1784f8b503b..a04b930976d047684a92412a34c472e3c9eede1c 100644 (file)
@@ -1 +1 @@
-869c30e45cc87063be423c650f16b99e8adb3df0
\ No newline at end of file
+91384a7d727ef0f285cd430e829ba9f3852db50e
\ No newline at end of file
index 8223d21611b2e0d061964e8fbb42a1afd532b30b..347b604bf4463315aa696e80ffe4419cc392d3e5 100644 (file)
@@ -214,6 +214,7 @@ static VdbeCursor *allocateCursor(
     memset(pCx, 0, sizeof(VdbeCursor));
     pCx->iDb = iDb;
     pCx->nField = nField;
+    pCx->aOffset = &pCx->aType[nField];
     if( isBtreeCursor ){
       pCx->pCursor = (BtCursor*)
           &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
@@ -2276,7 +2277,7 @@ case OP_Column: {
   pC = p->apCsr[pOp->p1];
   assert( pC!=0 );
   assert( p2<pC->nField );
-  aOffset = pC->aType + pC->nField;
+  aOffset = pC->aOffset;
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
 #endif
@@ -3563,7 +3564,6 @@ case OP_SeekGT: {       /* jump, in3 */
       applyNumericAffinity(pIn3, 0);
     }
     iKey = sqlite3VdbeIntValue(pIn3);
-    pC->rowidIsValid = 0;
 
     /* If the P3 value could not be converted into an integer without
     ** loss of information, then special processing is required... */
@@ -3599,13 +3599,10 @@ case OP_SeekGT: {       /* jump, in3 */
       }
     } 
     rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
+    pC->movetoTarget = iKey;  /* Used by OP_Delete */
     if( rc!=SQLITE_OK ){
       goto abort_due_to_error;
     }
-    if( res==0 ){
-      pC->rowidIsValid = 1;
-      pC->lastRowid = iKey;
-    }
   }else{
     nField = pOp->p4.i;
     assert( pOp->p4type==P4_INT32 );
@@ -3635,7 +3632,6 @@ case OP_SeekGT: {       /* jump, in3 */
     if( rc!=SQLITE_OK ){
       goto abort_due_to_error;
     }
-    pC->rowidIsValid = 0;
   }
   pC->deferredMoveto = 0;
   pC->cacheStatus = CACHE_STALE;
@@ -3647,7 +3643,6 @@ case OP_SeekGT: {       /* jump, in3 */
       res = 0;
       rc = sqlite3BtreeNext(pC->pCursor, &res);
       if( rc!=SQLITE_OK ) goto abort_due_to_error;
-      pC->rowidIsValid = 0;
     }else{
       res = 0;
     }
@@ -3657,7 +3652,6 @@ case OP_SeekGT: {       /* jump, in3 */
       res = 0;
       rc = sqlite3BtreePrevious(pC->pCursor, &res);
       if( rc!=SQLITE_OK ) goto abort_due_to_error;
-      pC->rowidIsValid = 0;
     }else{
       /* res might be negative because the table is empty.  Check to
       ** see if this is the case.
@@ -3694,7 +3688,6 @@ case OP_Seek: {    /* in2 */
   pC->nullRow = 0;
   pIn2 = &aMem[pOp->p2];
   pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
-  pC->rowidIsValid = 0;
   pC->deferredMoveto = 1;
   break;
 }
@@ -3880,15 +3873,13 @@ case OP_NotExists: {        /* jump, in3 */
   res = 0;
   iKey = pIn3->u.i;
   rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
-  pC->lastRowid = pIn3->u.i;
-  pC->rowidIsValid = res==0 ?1:0;
+  pC->movetoTarget = iKey;  /* Used by OP_Delete */
   pC->nullRow = 0;
   pC->cacheStatus = CACHE_STALE;
   pC->deferredMoveto = 0;
   VdbeBranchTaken(res!=0,2);
   if( res!=0 ){
     pc = pOp->p2 - 1;
-    assert( pC->rowidIsValid==0 );
   }
   pC->seekResult = res;
   break;
@@ -4036,7 +4027,6 @@ case OP_NewRowid: {           /* out2-prerelease */
       }
       assert( v>0 );  /* EV: R-40812-03570 */
     }
-    pC->rowidIsValid = 0;
     pC->deferredMoveto = 0;
     pC->cacheStatus = CACHE_STALE;
   }
@@ -4141,7 +4131,6 @@ case OP_InsertInt: {
                           pData->z, pData->n, nZero,
                           (pOp->p5 & OPFLAG_APPEND)!=0, seekResult
   );
-  pC->rowidIsValid = 0;
   pC->deferredMoveto = 0;
   pC->cacheStatus = CACHE_STALE;
 
@@ -4178,33 +4167,32 @@ case OP_InsertInt: {
 ** using OP_NotFound prior to invoking this opcode.
 */
 case OP_Delete: {
-  i64 iKey;
   VdbeCursor *pC;
 
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   pC = p->apCsr[pOp->p1];
   assert( pC!=0 );
   assert( pC->pCursor!=0 );  /* Only valid for real tables, no pseudotables */
-  iKey = pC->lastRowid;      /* Only used for the update hook */
-
-  /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
-  ** OP_Column on the same table without any intervening operations that
-  ** might move or invalidate the cursor.  Hence cursor pC is always pointing
-  ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
-  ** below is always a no-op and cannot fail.  We will run it anyhow, though,
-  ** to guard against future changes to the code generator.
-  **/
   assert( pC->deferredMoveto==0 );
-  rc = sqlite3VdbeCursorMoveto(pC);
-  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
 
+#ifdef SQLITE_DEBUG
+  /* The seek operation that positioned the cursor prior to OP_Delete will
+  ** have also set the pC->movetoTarget field to the rowid of the row that
+  ** is being deleted */
+  if( pOp->p4.z && pC->isTable ){
+    i64 iKey = 0;
+    sqlite3BtreeKeySize(pC->pCursor, &iKey);
+    assert( pC->movetoTarget==iKey ); 
+  }
+#endif
   rc = sqlite3BtreeDelete(pC->pCursor);
   pC->cacheStatus = CACHE_STALE;
 
   /* Invoke the update-hook if required. */
   if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){
     db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
-                        db->aDb[pC->iDb].zName, pOp->p4.z, iKey);
+                        db->aDb[pC->iDb].zName, pOp->p4.z, pC->movetoTarget);
     assert( pC->iDb>=0 );
   }
   if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
@@ -4396,12 +4384,8 @@ case OP_Rowid: {                 /* out2-prerelease */
     assert( pC->pCursor!=0 );
     rc = sqlite3VdbeCursorMoveto(pC);
     if( rc ) goto abort_due_to_error;
-    if( pC->rowidIsValid ){
-      v = pC->lastRowid;
-    }else{
-      rc = sqlite3BtreeKeySize(pC->pCursor, &v);
-      assert( rc==SQLITE_OK );  /* Always so because of CursorMoveto() above */
-    }
+    rc = sqlite3BtreeKeySize(pC->pCursor, &v);
+    assert( rc==SQLITE_OK );  /* Always so because of CursorMoveto() above */
   }
   pOut->u.i = v;
   break;
@@ -4420,7 +4404,6 @@ case OP_NullRow: {
   pC = p->apCsr[pOp->p1];
   assert( pC!=0 );
   pC->nullRow = 1;
-  pC->rowidIsValid = 0;
   pC->cacheStatus = CACHE_STALE;
   if( pC->pCursor ){
     sqlite3BtreeClearCursor(pC->pCursor);
@@ -4454,7 +4437,6 @@ case OP_Last: {        /* jump */
   rc = sqlite3BtreeLast(pCrsr, &res);
   pC->nullRow = (u8)res;
   pC->deferredMoveto = 0;
-  pC->rowidIsValid = 0;
   pC->cacheStatus = CACHE_STALE;
 #ifdef SQLITE_DEBUG
   pC->seekOp = OP_Last;
@@ -4521,7 +4503,6 @@ case OP_Rewind: {        /* jump */
     rc = sqlite3BtreeFirst(pCrsr, &res);
     pC->deferredMoveto = 0;
     pC->cacheStatus = CACHE_STALE;
-    pC->rowidIsValid = 0;
   }
   pC->nullRow = (u8)res;
   assert( pOp->p2>0 && pOp->p2<p->nOp );
@@ -4647,7 +4628,6 @@ next_tail:
   }else{
     pC->nullRow = 1;
   }
-  pC->rowidIsValid = 0;
   goto check_for_interrupt;
 }
 
index aa1132e31c366c63bacd4da3932d981f8334f8a5..1c7bebc9f66af087c43bef6c2a2766281570316b 100644 (file)
@@ -73,7 +73,6 @@ struct VdbeCursor {
 #endif
   i8 iDb;               /* Index of cursor database in db->aDb[] (or -1) */
   u8 nullRow;           /* True if pointing to a row with no data */
-  u8 rowidIsValid;      /* True if lastRowid is valid */
   u8 deferredMoveto;    /* A call to sqlite3BtreeMoveto() is needed */
   Bool isEphemeral:1;   /* True for an ephemeral table */
   Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
@@ -83,7 +82,6 @@ struct VdbeCursor {
   sqlite3_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
   i64 seqCount;         /* Sequence counter */
   i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
-  i64 lastRowid;        /* Rowid being deleted by OP_Delete */
   VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
 
   /* Cached information about the header for the data record that the
@@ -100,6 +98,7 @@ struct VdbeCursor {
   u32 szRow;            /* Byte available in aRow */
   u32 iHdrOffset;       /* Offset to next unparsed byte of the header */
   const u8 *aRow;       /* Data for the current row, if all on one page */
+  u32 *aOffset;         /* Pointer to aType[nField] */
   u32 aType[1];         /* Type values for all entries in the record */
   /* 2*nField extra array elements allocated for aType[], beyond the one
   ** static element declared in the structure.  nField total array slots for
index 33fa055369084bd3c2f95c409871eb627e550aee..fefa0ef3377cf7a263c0ee2a4dde1bc4fb247398 100644 (file)
@@ -2718,9 +2718,7 @@ static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
   assert( p->isTable );
   rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
   if( rc ) return rc;
-  p->lastRowid = p->movetoTarget;
   if( res!=0 ) return SQLITE_CORRUPT_BKPT;
-  p->rowidIsValid = 1;
 #ifdef SQLITE_TEST
   sqlite3_search_count++;
 #endif