diff options
author | drh <drh@noemail.net> | 2013-07-10 03:05:14 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2013-07-10 03:05:14 +0000 |
commit | 49afe3aaa067eb050d0e831d351683c8251cba42 (patch) | |
tree | a67c9dc2b68ddbafda0fe139d596f6ad56861a8c /src | |
parent | 580d7dc71d0a5f820df8062d76e8b27590ff5fcc (diff) | |
download | sqlite-49afe3aaa067eb050d0e831d351683c8251cba42.tar.gz sqlite-49afe3aaa067eb050d0e831d351683c8251cba42.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/vdbe.c | 72 |
1 files changed, 38 insertions, 34 deletions
diff --git a/src/vdbe.c b/src/vdbe.c index f539b400a..9a56518c5 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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 */ |