Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3e8b02011db2f393d4850115a471709b |
User & Date: | drh 2013-07-10 03:05:14.910 |
Context
2013-07-10
| ||
18:14 | Fix harmless compiler warnings in the progress callback logic. (check-in: 908141d5bf user: drh tags: trunk) | |
13:33 | Experimental "PRAGMA query_only=BOOLEAN" statement that is able to turn write capabilities on and off. (Closed-Leaf check-in: ece960c496 user: drh tags: query_only) | |
03:05 | 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. (check-in: 3e8b02011d user: drh tags: trunk) | |
2013-07-09
| ||
15:56 | Adjust the costs in the xBestIndex function of the spellfix1 virtual table to force the use of the MATCH term if it is available. (check-in: f003bea9fe user: drh tags: trunk) | |
Changes
Changes to src/vdbe.c.
︙ | ︙ | |||
548 549 550 551 552 553 554 555 | int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ 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 | > > < | < < | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | int pc=0; /* The program counter */ Op *aOp = p->aOp; /* Copy of p->aOp */ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ 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 */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ int *aPermute = 0; /* Permutation of columns for OP_Compare */ i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */ |
︙ | ︙ | |||
582 583 584 585 586 587 588 | assert( p->bIsReader || p->readOnly!=0 ); p->rc = SQLITE_OK; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); | < < < | 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | assert( p->bIsReader || p->readOnly!=0 ); p->rc = SQLITE_OK; assert( p->explain==0 ); p->pResultSet = 0; db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); #ifdef SQLITE_DEBUG sqlite3BeginBenignMalloc(); if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){ int i; printf("VDBE Program Listing:\n"); sqlite3VdbePrintSql(p); for(i=0; i<p->nOp; i++){ |
︙ | ︙ | |||
630 631 632 633 634 635 636 | #ifdef SQLITE_TEST if( sqlite3_interrupt_count>0 ){ sqlite3_interrupt_count--; if( sqlite3_interrupt_count==0 ){ sqlite3_interrupt(db); } } | < < < < < < < < < < < < < < < < < < < < < | 626 627 628 629 630 631 632 633 634 635 636 637 638 639 | #ifdef SQLITE_TEST if( sqlite3_interrupt_count>0 ){ sqlite3_interrupt_count--; if( sqlite3_interrupt_count==0 ){ sqlite3_interrupt(db); } } #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 ** value or convert mem[p2] to a different type. */ |
︙ | ︙ | |||
745 746 747 748 749 750 751 752 | ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. */ case OP_Goto: { /* jump */ CHECK_FOR_INTERRUPT; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | ** ** An unconditional jump to address P2. ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. */ case OP_Goto: { /* jump */ 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; } /* Opcode: Gosub P1 P2 * * * ** ** Write the current address onto register P1 ** and then jump to address P2. |
︙ | ︙ | |||
4498 4499 4500 4501 4502 4503 4504 | */ case OP_SorterNext: /* jump */ case OP_Prev: /* jump */ case OP_Next: { /* jump */ VdbeCursor *pC; int res; | < | 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 | */ case OP_SorterNext: /* jump */ case OP_Prev: /* jump */ case OP_Next: { /* jump */ VdbeCursor *pC; int res; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p5<=ArraySize(p->aCounter) ); pC = p->apCsr[pOp->p1]; if( pC==0 ){ break; /* See ticket #2273 */ } assert( pC->isSorter==(pOp->opcode==OP_SorterNext) ); |
︙ | ︙ | |||
4527 4528 4529 4530 4531 4532 4533 | pc = pOp->p2 - 1; if( pOp->p5 ) p->aCounter[pOp->p5-1]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif } pC->rowidIsValid = 0; | | | 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 | pc = pOp->p2 - 1; if( pOp->p5 ) p->aCounter[pOp->p5-1]++; #ifdef SQLITE_TEST sqlite3_search_count++; #endif } pC->rowidIsValid = 0; goto check_for_interrupt; } /* Opcode: IdxInsert P1 P2 P3 * P5 ** ** Register P2 holds an SQL index key made using the ** MakeRecord instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. |
︙ | ︙ | |||
5053 5054 5055 5056 5057 5058 5059 | ** ** Extract the smallest value from boolean index P1 and put that value into ** register P3. Or, if boolean index P1 is initially empty, leave P3 ** unchanged and jump to instruction P2. */ case OP_RowSetRead: { /* jump, in1, out3 */ i64 val; | | | | 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 | ** ** Extract the smallest value from boolean index P1 and put that value into ** register P3. Or, if boolean index P1 is initially empty, leave P3 ** unchanged and jump to instruction P2. */ case OP_RowSetRead: { /* jump, in1, out3 */ i64 val; pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_RowSet)==0 || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 ){ /* The boolean index is empty */ sqlite3VdbeMemSetNull(pIn1); pc = pOp->p2 - 1; }else{ /* A value was pulled from the index */ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); } goto check_for_interrupt; } /* Opcode: RowSetTest P1 P2 P3 P4 ** ** Register P3 is assumed to hold a 64-bit integer value. If register P1 ** contains a RowSet object and that RowSet object contains ** the value held in P3, jump to register P2. Otherwise, insert the |
︙ | ︙ | |||
5966 5967 5968 5969 5970 5971 5972 | res = pModule->xEof(pCur->pVtabCursor); } if( !res ){ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; } | | | 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 | res = pModule->xEof(pCur->pVtabCursor); } if( !res ){ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; } goto check_for_interrupt; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VRename P1 * * P4 * ** ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure. |
︙ | ︙ |
Changes to test/progress.test.
︙ | ︙ | |||
162 163 164 165 166 167 168 | INSERT INTO abc VALUES(4, 5, 6); INSERT INTO abc VALUES(7, 8, 9); } set ::res [list] db eval {SELECT a, b, c FROM abc} { lappend ::res $a $b $c | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | INSERT INTO abc VALUES(4, 5, 6); INSERT INTO abc VALUES(7, 8, 9); } set ::res [list] db eval {SELECT a, b, c FROM abc} { lappend ::res $a $b $c db progress 5 "expr 1" catch {db eval {SELECT a, b, c FROM abc} { }} msg lappend ::res $msg } set ::res } {1 2 3 interrupted 4 5 6 interrupted 7 8 9 interrupted} |
︙ | ︙ |