1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Run progress callback checks less frequently in the main VDBE evaluation

loop.  This makes up for the extra CPU cycles used to increment the cycle
counter for SQLITE_STMTSTATUS_VM_STEP.

FossilOrigin-Name: 3e8b02011db2f393d4850115a471709b0a88594f
This commit is contained in:
drh
2013-07-10 03:05:14 +00:00
parent 580d7dc71d
commit 49afe3aaa0
4 changed files with 47 additions and 43 deletions

View File

@@ -552,12 +552,11 @@ int sqlite3VdbeExec(
sqlite3 *db = p->db; /* The database */
u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
u8 encoding = ENC(db); /* The database encoding */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int checkProgress; /* True if progress callbacks are enabled */
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif
int iCompare = 0; /* Result of last OP_Compare operation */
unsigned nVmStep = 0; /* Number of virtual machine steps */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
unsigned nProgressOps = 0; /* nVmStep at last progress callback. */
#endif
Mem *aMem = p->aMem; /* Copy of p->aMem */
Mem *pIn1 = 0; /* 1st input operand */
Mem *pIn2 = 0; /* 2nd input operand */
@@ -586,9 +585,6 @@ int sqlite3VdbeExec(
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
checkProgress = db->xProgress!=0;
#endif
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){
@@ -636,27 +632,6 @@ int sqlite3VdbeExec(
}
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
** sqlite3VdbeExec() or since last time the progress callback was called).
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( checkProgress ){
if( db->nProgressOps==nProgressOps ){
int prc;
prc = db->xProgress(db->pProgressArg);
if( prc!=0 ){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
}
nProgressOps = 0;
}
nProgressOps++;
}
#endif
/* On any opcode with the "out2-prerelease" tag, free any
** external allocations out of mem[p2] and set mem[p2] to be
** an undefined integer. Opcodes will either fill in the integer
@@ -749,8 +724,38 @@ int sqlite3VdbeExec(
** the program.
*/
case OP_Goto: { /* jump */
CHECK_FOR_INTERRUPT;
pc = pOp->p2 - 1;
/* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
** completion. Check to see if sqlite3_interrupt() has been called
** or if the progress callback needs to be invoked.
**
** This code uses unstructured "goto" statements and does not look clean.
** But that is not due to sloppy coding habits. The code is written this
** way for performance, to avoid having to run the interrupt and progress
** checks on every opcode. This helps sqlite3_step() to run about 1.5%
** faster according to "valgrind --tool=cachegrind" */
check_for_interrupt:
CHECK_FOR_INTERRUPT;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
** sqlite3VdbeExec() or since last time the progress callback was called).
** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT.
*/
if( db->xProgress!=0 && (nVmStep - nProgressOps)>=db->nProgressOps ){
int prc;
prc = db->xProgress(db->pProgressArg);
if( prc!=0 ){
rc = SQLITE_INTERRUPT;
goto vdbe_error_halt;
}
nProgressOps = nVmStep;
}
#endif
break;
}
@@ -4502,7 +4507,6 @@ case OP_Next: { /* jump */
VdbeCursor *pC;
int res;
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5<=ArraySize(p->aCounter) );
pC = p->apCsr[pOp->p1];
@@ -4531,7 +4535,7 @@ case OP_Next: { /* jump */
#endif
}
pC->rowidIsValid = 0;
break;
goto check_for_interrupt;
}
/* Opcode: IdxInsert P1 P2 P3 * P5
@@ -5057,7 +5061,7 @@ case OP_RowSetAdd: { /* in1, in2 */
*/
case OP_RowSetRead: { /* jump, in1, out3 */
i64 val;
CHECK_FOR_INTERRUPT;
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_RowSet)==0
|| sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
@@ -5069,7 +5073,7 @@ case OP_RowSetRead: { /* jump, in1, out3 */
/* A value was pulled from the index */
sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
}
break;
goto check_for_interrupt;
}
/* Opcode: RowSetTest P1 P2 P3 P4
@@ -5970,7 +5974,7 @@ case OP_VNext: { /* jump */
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
break;
goto check_for_interrupt;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */