From 4774b13029b803ce938345a4e1150d7f54acdefc Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 12 Jun 2004 20:12:51 +0000 Subject: [PATCH] Speed up in the handling of VDBE cursors. (CVS 1578) FossilOrigin-Name: e42316f5708de6f639b7b54e08d4be73b45367e9 --- manifest | 16 +++++------ manifest.uuid | 2 +- src/vdbe.c | 80 ++++++++++++++++++++++++++++++++------------------- src/vdbeInt.h | 3 +- src/vdbeaux.c | 11 +++---- 5 files changed, 67 insertions(+), 45 deletions(-) diff --git a/manifest b/manifest index 42030e5a20..eda87be02c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sthe\sspeed\sof\sOP_Column\sthrough\sbetter\scaching.\s(CVS\s1577) -D 2004-06-12T18:12:16 +C Speed\sup\sin\sthe\shandling\sof\sVDBE\scursors.\s(CVS\s1578) +D 2004-06-12T20:12:51 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -71,11 +71,11 @@ F src/update.c 168b6d523087ca4545b74ec9f3102b1f3c6b1e38 F src/utf.c e16737b3fc4201bf7ce9bd8ced5250596aa31b76 F src/util.c 90375fa253137562d536ccdd40b297f0fd7413fc F src/vacuum.c b921eb778842592e1fb48a9d4cef7e861103878f -F src/vdbe.c 9f941bbdf0bcbc18fbdfceecbc2322e82084e094 +F src/vdbe.c c71e47262d3d3539a20a489a03b9cde15ef3acb7 F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde -F src/vdbeInt.h 1cc767a63eefd1d1114e190336588c6d4f70a6a0 +F src/vdbeInt.h ffc7b8ed911c5bf804796a768fdb6f0568010fa2 F src/vdbeapi.c ee350b552fc4c1c695b760f914f69e9c5556e829 -F src/vdbeaux.c 1d0dbaf73c89bd1cc27abad19ee0aa26ab5d03f4 +F src/vdbeaux.c ff7c66b704dc2c35805657f2cb10ad1b00c8ecd2 F src/vdbemem.c 34f59988831ea032b7f526c2c73175f9f4c0f3ad F src/where.c dda77afaa593cd54e5955ec433076de18faf62f6 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 @@ -223,7 +223,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 99a7bd83ac38e14bb936a834634313cf98279a62 -R 1e1692dcb3026c03937468eb4d723051 +P f687977a28eda5ce0aa1cba2fdfb0152443032bc +R 088c58f79c616faca7f8012c3563c5db U drh -Z 511db11f04adc59072cae9559d18a6b6 +Z 661048d261d615dd2ffa1c2c62f56278 diff --git a/manifest.uuid b/manifest.uuid index 3a7b8c7357..8db71c8278 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f687977a28eda5ce0aa1cba2fdfb0152443032bc \ No newline at end of file +e42316f5708de6f639b7b54e08d4be73b45367e9 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 4c1faef212..9057e0de4e 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.369 2004/06/12 18:12:16 drh Exp $ +** $Id: vdbe.c,v 1.370 2004/06/12 20:12:51 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -271,24 +271,27 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight, KeyInfo *pKeyInfo){ } /* -** Make sure there is space in the Vdbe structure to hold at least -** mxCursor cursors. If there is not currently enough space, then -** allocate more. -** -** If a memory allocation error occurs, return 1. Return 0 if -** everything works. -*/ -static int expandCursorArraySize(Vdbe *p, int mxCursor){ - if( mxCursor>=p->nCursor ){ - p->apCsr = sqliteRealloc( p->apCsr, (mxCursor+1)*sizeof(Cursor*) ); - if( p->apCsr==0 ) return 1; - while( p->nCursor<=mxCursor ){ - Cursor *pC; - p->apCsr[p->nCursor++] = pC = sqliteMalloc( sizeof(Cursor) ); - if( pC==0 ) return 1; +** Allocate cursor number iCur. Return a pointer to it. Return NULL +** if we run out of memory. +*/ +static Cursor *allocateCursor(Vdbe *p, int iCur){ + Cursor *pCx; + if( iCur>=p->nCursor ){ + int i; + p->apCsr = sqliteRealloc( p->apCsr, (iCur+1)*sizeof(Cursor*) ); + if( p->apCsr==0 ){ + p->nCursor = 0; + return 0; } + for(i=p->nCursor; iapCsr[i] = 0; + } + p->nCursor = iCur+1; + }else if( p->apCsr[iCur] ){ + sqlite3VdbeFreeCursor(p->apCsr[iCur]); } - return 0; + p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) ); + return pCx; } /* @@ -1867,6 +1870,7 @@ case OP_NotNull: { */ case OP_SetNumColumns: { assert( (pOp->p1)nCursor ); + assert( p->apCsr[pOp->p1]!=0 ); p->apCsr[pOp->p1]->nField = pOp->p2; break; } @@ -1931,6 +1935,7 @@ case OP_Column: { ** records on the stack, the next entry down on the stack is an integer ** which is the number of records. */ + assert( p1<0 || p->apCsr[p1]!=0 ); if( p1<0 ){ /* Take the record off of the stack */ Mem *pRec = &pTos[p1]; @@ -2572,9 +2577,8 @@ case OP_OpenWrite: { } } assert( i>=0 ); - if( expandCursorArraySize(p, i) ) goto no_mem; - pCur = p->apCsr[i]; - sqlite3VdbeCleanupCursor(pCur); + pCur = allocateCursor(p, i); + if( pCur==0 ) goto no_mem; pCur->nullRow = 1; if( pX==0 ) break; /* We always provide a key comparison function. If the table being @@ -2635,10 +2639,8 @@ case OP_OpenTemp: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); - if( expandCursorArraySize(p, i) ) goto no_mem; - pCx = p->apCsr[i]; - sqlite3VdbeCleanupCursor(pCx); - memset(pCx, 0, sizeof(*pCx)); + pCx = allocateCursor(p, i); + if( pCx==0 ) goto no_mem; pCx->nullRow = 1; rc = sqlite3BtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt); @@ -2686,10 +2688,8 @@ case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); - if( expandCursorArraySize(p, i) ) goto no_mem; - pCx = p->apCsr[i]; - sqlite3VdbeCleanupCursor(pCx); - memset(pCx, 0, sizeof(*pCx)); + pCx = allocateCursor(p, i); + if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->pseudoTable = 1; pCx->pIncrKey = &pCx->bogusIncrKey; @@ -2704,7 +2704,8 @@ case OP_OpenPseudo: { case OP_Close: { int i = pOp->p1; if( i>=0 && inCursor ){ - sqlite3VdbeCleanupCursor(p->apCsr[i]); + sqlite3VdbeFreeCursor(p->apCsr[i]); + p->apCsr[i] = 0; } break; } @@ -2759,6 +2760,7 @@ case OP_MoveGt: { assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); pC = p->apCsr[i]; + assert( pC!=0 ); if( pC->pCursor!=0 ){ int res, oc; oc = pOp->opcode; @@ -2858,6 +2860,7 @@ case OP_Found: { Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor!=0 ){ int res, rx; assert( pC->intKey==0 ); @@ -2915,6 +2918,7 @@ case OP_IsUnique: { pTos--; assert( i>=0 && i<=p->nCursor ); pCx = p->apCsr[i]; + assert( pCx!=0 ); pCrsr = pCx->pCursor; if( pCrsr!=0 ){ int res, rc; @@ -2998,6 +3002,7 @@ case OP_NotExists: { BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res, rx; u64 iKey; @@ -3031,6 +3036,7 @@ case OP_NewRecno: { i64 v = 0; Cursor *pC; assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor==0 ){ /* The zero initialization above is all that is needed */ }else{ @@ -3159,6 +3165,7 @@ case OP_PutStrKey: { Cursor *pC; assert( pNos>=p->aStack ); assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){ char *zKey; i64 nKey; @@ -3249,6 +3256,7 @@ case OP_Delete: { Cursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; + assert( pC!=0 ); if( pC->pCursor!=0 ){ sqlite3VdbeCursorMoveto(pC); rc = sqlite3BtreeDelete(pC->pCursor); @@ -3283,6 +3291,7 @@ case OP_KeyAsData: { Cursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; + assert( pC!=0 ); pC->keyAsData = pOp->p2; break; } @@ -3314,6 +3323,7 @@ case OP_RowData: { pTos++; assert( i>=0 && inCursor ); pC = p->apCsr[i]; + assert( pC!=0 ); if( pC->nullRow ){ pTos->flags = MEM_Null; }else if( pC->pCursor!=0 ){ @@ -3370,6 +3380,7 @@ case OP_Recno: { assert( i>=0 && inCursor ); pC = p->apCsr[i]; + assert( pC!=0 ); sqlite3VdbeCursorMoveto(pC); pTos++; if( pC->recnoIsValid ){ @@ -3405,9 +3416,10 @@ case OP_FullKey: { BtCursor *pCrsr; Cursor *pC; + assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); assert( p->apCsr[i]->keyAsData ); assert( !p->apCsr[i]->pseudoTable ); - assert( i>=0 && inCursor ); pTos++; if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ u64 amt; @@ -3448,6 +3460,7 @@ case OP_NullRow: { assert( i>=0 && inCursor ); pC = p->apCsr[i]; + assert( pC!=0 ); pC->nullRow = 1; pC->recnoIsValid = 0; break; @@ -3468,6 +3481,7 @@ case OP_Last: { assert( i>=0 && inCursor ); pC = p->apCsr[i]; + assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqlite3BtreeLast(pCrsr, &res); @@ -3499,6 +3513,7 @@ case OP_Rewind: { assert( i>=0 && inCursor ); pC = p->apCsr[i]; + assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ rc = sqlite3BtreeFirst(pCrsr, &res); pC->atFirst = res==0; @@ -3538,6 +3553,7 @@ case OP_Next: { CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); if( (pCrsr = pC->pCursor)!=0 ){ int res; if( pC->nullRow ){ @@ -3577,6 +3593,7 @@ case OP_IdxPut: { BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); assert( pTos->flags & MEM_Blob ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int nKey = pTos->n; @@ -3629,6 +3646,7 @@ case OP_IdxDelete: { assert( pTos>=p->aStack ); assert( pTos->flags & MEM_Blob ); assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int rx, res; rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res); @@ -3657,6 +3675,7 @@ case OP_IdxRecno: { Cursor *pC; assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); pTos++; if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ i64 rowid; @@ -3763,6 +3782,7 @@ case OP_IdxGE: { Cursor *pC; assert( i>=0 && inCursor ); + assert( p->apCsr[i]!=0 ); assert( pTos>=p->aStack ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res, rc; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 39f27c1f60..cb4ac818d2 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -62,6 +62,7 @@ struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ i64 lastRecno; /* Last recno from a Next or NextIdx operation */ i64 nextRowid; /* Next rowid returned by OP_NewRowid */ + Bool zeroed; /* True if zeroed out and ready for reuse */ Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ @@ -352,7 +353,7 @@ struct Vdbe { /* ** Function prototypes */ -void sqlite3VdbeCleanupCursor(Cursor*); +void sqlite3VdbeFreeCursor(Cursor*); void sqlite3VdbeSorterReset(Vdbe*); int sqlite3VdbeAggReset(sqlite *, Agg *, KeyInfo *); void sqlite3VdbeKeylistFree(Keylist*); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index fbf21483d8..7836f1330e 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -826,7 +826,10 @@ void sqlite3VdbeKeylistFree(Keylist *p){ ** Close a cursor and release all the resources that cursor happens ** to hold. */ -void sqlite3VdbeCleanupCursor(Cursor *pCx){ +void sqlite3VdbeFreeCursor(Cursor *pCx){ + if( pCx==0 ){ + return; + } if( pCx->pCursor ){ sqlite3BtreeCloseCursor(pCx->pCursor); } @@ -835,7 +838,7 @@ void sqlite3VdbeCleanupCursor(Cursor *pCx){ } sqliteFree(pCx->pData); sqliteFree(pCx->aType); - memset(pCx, 0, sizeof(*pCx)); + sqliteFree(pCx); } /* @@ -844,9 +847,7 @@ void sqlite3VdbeCleanupCursor(Cursor *pCx){ static void closeAllCursors(Vdbe *p){ int i; for(i=0; inCursor; i++){ - Cursor *pC = p->apCsr[i]; - sqlite3VdbeCleanupCursor(pC); - sqliteFree(pC); + sqlite3VdbeFreeCursor(p->apCsr[i]); } sqliteFree(p->apCsr); p->apCsr = 0; -- 2.47.3