diff --git a/manifest b/manifest index f02230ee0d..037c3a5ddd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Optimized\svarint\sroutines\sand\stests\sadded.\s(CVS\s1380) -D 2004-05-14T16:50:06 +C More\sspeed\simprovements.\s(CVS\s1381) +D 2004-05-14T19:08:18 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -23,7 +23,7 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5 F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79 -F src/btree.c 71c689f16d00febbdee5f474b9bc570df404a7fc +F src/btree.c c263f1f26b28e0ac929b9807bccf50877335c1b8 F src/btree.h 6f51ad0ffebfba71295fcacdbe86007512200050 F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5 F src/build.c e93f443a20eab57ffb77ff6244b1e09a1f7d9390 @@ -66,7 +66,7 @@ F src/vacuum.c c134702e023db8778e6be59ac0ea7b02315b5476 F src/vdbe.c fff79c08b3063d8d6f7b600fc6896c255c72238c F src/vdbe.h 94457ca73bae972dc61bca33a4dccc2e6e14e2f8 F src/vdbeInt.h 03f4c3642482570a697a42a9bbb12908c6535bbe -F src/vdbeaux.c 4590e8f5e064ee1e269a0b969f6f28118daf325d +F src/vdbeaux.c 6cf897c49c1fde153d8b9e4c168714207f07cce3 F src/where.c 6957bbd333cc7ffa7b3878adbe67a095319daa54 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83 @@ -191,7 +191,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P cad47917267d32ab00c8b949151c8bc3c6638479 -R 2f283a670b4184db072fa201634f4b5a +P d4e0933dc72b66157164610e0b03f339bc535fb9 +R 9330d9bd11be003784ef684f1b9c1f25 U drh -Z a43ba40aa94121177ed5f96de31aa3ea +Z 185a62bf4f1e1cc9ef6d8083626f74a6 diff --git a/manifest.uuid b/manifest.uuid index 30e45c0443..a1785d8dd1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d4e0933dc72b66157164610e0b03f339bc535fb9 \ No newline at end of file +cf75cac9b6bd43e60c6e25042b194ec5c60e5671 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 54e13ad082..099d4a09e2 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.137 2004/05/14 16:50:06 drh Exp $ +** $Id: btree.c,v 1.138 2004/05/14 19:08:18 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -279,6 +279,20 @@ struct Btree { }; typedef Btree Bt; +/* +** An instance of the following structure is used to hold information +** about a cell. The parseCell() function fills the structure in. +*/ +typedef struct CellInfo CellInfo; +struct CellInfo { + i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ + u32 nData; /* Number of bytes of data */ + u16 nHeader; /* Size of the header in bytes */ + u16 nLocal; /* Amount of payload held locally */ + u16 iOverflow; /* Offset to overflow page number. Zero if none */ + u16 nSize; /* Size of the cell */ +}; + /* ** A cursor is a pointer to a particular entry in the BTree. ** The entry is identified by its MemPage and the index in @@ -293,26 +307,14 @@ struct BtCursor { Pgno pgnoRoot; /* The root page of this tree */ MemPage *pPage; /* Page that contains the entry */ int idx; /* Index of the entry in pPage->aCell[] */ + CellInfo info; /* A parse of the cell we are pointing at */ + u8 infoValid; /* True if information in BtCursor.info is valid */ u8 wrFlag; /* True if writable */ u8 iMatch; /* compare result from last sqlite3BtreeMoveto() */ u8 isValid; /* TRUE if points to a valid entry */ u8 status; /* Set to SQLITE_ABORT if cursors is invalidated */ }; -/* -** An instance of the following structure is used to hold information -** about a cell. The parseCell() function fills the structure in. -*/ -typedef struct CellInfo CellInfo; -struct CellInfo { - i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ - u32 nData; /* Number of bytes of data */ - int nHeader; /* Size of the header in bytes */ - int nLocal; /* Amount of payload held locally */ - int iOverflow; /* Offset to overflow page number. Zero if none */ - int nSize; /* Size of the cell */ -}; - /* ** Read or write a two-, four-, and eight-byte big-endian integer values. */ @@ -675,7 +677,12 @@ static void freeSpace(MemPage *pPage, int start, int size){ */ static int resizeCellArray(MemPage *pPage, int nNewSz){ if( pPage->nCellAllocaCell = sqliteRealloc(pPage->aCell, nNewSz*sizeof(pPage->aCell[0]) ); + int n = nNewSz*sizeof(pPage->aCell[0]); + if( pPage->aCell==0 ){ + pPage->aCell = sqliteMallocRaw( n ); + }else{ + pPage->aCell = sqliteRealloc(pPage->aCell, n); + } if( sqlite3_malloc_failed ) return SQLITE_NOMEM; pPage->nCellAlloc = nNewSz; } @@ -1374,6 +1381,7 @@ int sqlite3BtreeCursor( pCur->pBt = pBt; pCur->wrFlag = wrFlag; pCur->idx = 0; + pCur->infoValid = 0; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ pCur->pNext->pPrev = pCur; @@ -1538,7 +1546,7 @@ static int getPayload( MemPage *pPage; Btree *pBt; int ovflSize; - CellInfo info; + u32 nKey; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->isValid ); @@ -1547,22 +1555,33 @@ static int getPayload( pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idxnCell ); aPayload = pPage->aCell[pCur->idx]; - parseCell(pPage, aPayload, &info); - aPayload += info.nHeader; + if( !pCur->infoValid ){ + parseCell(pPage, aPayload, &pCur->info); + pCur->infoValid = 1; + }else{ +#ifndef NDEBUG + CellInfo info; + parseCell(pPage, aPayload, &info); + assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); +#endif + } + aPayload += pCur->info.nHeader; if( pPage->intKey ){ - info.nKey = 0; + nKey = 0; + }else{ + nKey = pCur->info.nKey; } assert( offset>=0 ); if( skipKey ){ - offset += info.nKey; + offset += nKey; } - if( offset+amt > info.nKey+info.nData ){ + if( offset+amt > nKey+pCur->info.nData ){ return SQLITE_ERROR; } - if( offsetinfo.nLocal ){ int a = amt; - if( a+offset>info.nLocal ){ - a = info.nLocal - offset; + if( a+offset>pCur->info.nLocal ){ + a = pCur->info.nLocal - offset; } memcpy(pBuf, &aPayload[offset], a); if( a==amt ){ @@ -1572,10 +1591,10 @@ static int getPayload( pBuf += a; amt -= a; }else{ - offset -= info.nLocal; + offset -= pCur->info.nLocal; } if( amt>0 ){ - nextPage = get4byte(&aPayload[info.nLocal]); + nextPage = get4byte(&aPayload[pCur->info.nLocal]); } ovflSize = pBt->usableSize - 4; while( amt>0 && nextPage ){ @@ -1674,7 +1693,8 @@ static const unsigned char *fetchPayload( unsigned char *aPayload; MemPage *pPage; Btree *pBt; - CellInfo info; + u32 nKey; + int nLocal; assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->isValid ); @@ -1683,21 +1703,33 @@ static const unsigned char *fetchPayload( pageIntegrity(pPage); assert( pCur->idx>=0 && pCur->idxnCell ); aPayload = pPage->aCell[pCur->idx]; - parseCell(pPage, aPayload, &info); - aPayload += info.nHeader; + if( !pCur->infoValid ){ + parseCell(pPage, aPayload, &pCur->info); + pCur->infoValid = 1; + }else{ +#ifndef NDEBUG + CellInfo info; + parseCell(pPage, aPayload, &info); + assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); +#endif + } + aPayload += pCur->info.nHeader; if( pPage->intKey ){ - info.nKey = 0; + nKey = 0; + }else{ + nKey = pCur->info.nKey; } if( skipKey ){ - aPayload += info.nKey; - info.nLocal -= info.nKey; - if( amt<0 ) amt = info.nData; - assert( amt<=info.nData ); + aPayload += nKey; + nLocal = pCur->info.nLocal - nKey; + if( amt<0 ) amt = pCur->info.nData; + assert( amt<=pCur->info.nData ); }else{ - if( amt<0 ) amt = info.nKey; - assert( amt<=info.nKey ); + nLocal = pCur->info.nLocal; + if( amt<0 ) amt = nKey; + assert( amt<=nKey ); } - if( amt>info.nLocal ){ + if( amt>nLocal ){ return 0; /* If any of the data is not local, return nothing */ } return aPayload; @@ -1750,6 +1782,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ releasePage(pOldPage); pCur->pPage = pNewPage; pCur->idx = 0; + pCur->infoValid = 0; if( pNewPage->nCell<1 ){ return SQLITE_CORRUPT; } @@ -1800,6 +1833,7 @@ static void moveToParent(BtCursor *pCur){ oldPgno = pPage->pgno; releasePage(pPage); pCur->pPage = pParent; + pCur->infoValid = 0; assert( pParent->idxShift==0 ); if( pParent->idxShift==0 ){ pCur->idx = idxParent; @@ -1847,6 +1881,7 @@ static int moveToRoot(BtCursor *pCur){ pageIntegrity(pRoot); pCur->pPage = pRoot; pCur->idx = 0; + pCur->infoValid = 0; if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; assert( pRoot->pgno==1 ); @@ -1898,6 +1933,7 @@ static int moveToRightmost(BtCursor *pCur){ if( rc ) return rc; } pCur->idx = pPage->nCell - 1; + pCur->infoValid = 0; return SQLITE_OK; } @@ -2000,6 +2036,7 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ const void *pCellKey; i64 nCellKey; pCur->idx = (lwr+upr)/2; + pCur->infoValid = 0; sqlite3BtreeKeySize(pCur, &nCellKey); if( pPage->intKey ){ if( nCellKeyidx = lwr; + pCur->infoValid = 0; rc = moveToChild(pCur, chldPg); if( rc ){ return rc; @@ -2089,6 +2127,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ assert( pPage->isInit ); assert( pCur->idxnCell ); pCur->idx++; + pCur->infoValid = 0; if( pCur->idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+6])); @@ -2155,6 +2194,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ pPage = pCur->pPage; } pCur->idx--; + pCur->infoValid = 0; if( pPage->leafData ){ rc = sqlite3BtreePrevious(pCur, pRes); }else{ @@ -2613,6 +2653,47 @@ static void insertCell( pPage->idxShift = 1; } +/* +** Add a list of cells to a page. The page should be initially empty. +** The cells are guaranteed to fit on the page. +*/ +static void assemblePage( + MemPage *pPage, /* The page to be assemblied */ + int nCell, /* The number of cells to add to this page */ + u8 **apCell, /* Pointers to cell text */ + int *aSize /* Sizes of the cells */ +){ + int i; /* Loop counter */ + int totalSize; /* Total size of all cells */ + int hdr; /* Index of page header */ + int pc, prevpc; /* Addresses of cells being inserted */ + u8 *data; /* Data for the page */ + + assert( pPage->needRelink==0 ); + assert( pPage->isOverfull==0 ); + totalSize = 0; + for(i=0; inFree ); + assert( pPage->nCell==0 ); + resizeCellArray(pPage, nCell); + pc = allocateSpace(pPage, totalSize); + data = pPage->aData; + hdr = pPage->hdrOffset; + prevpc = hdr+3; + for(i=0; iaCell[i] = data+pc; + prevpc = pc; + pc += aSize[i]; + assert( pc<=pPage->pBt->usableSize ); + } + pPage->nCell = nCell; + put2byte(data+prevpc, 0); +} + /* ** Rebuild the linked list of cells on a page so that the cells ** occur in the order specified by the pPage->aCell[] array. @@ -2810,11 +2891,10 @@ static int balance(MemPage *pPage){ /* The child information will fit on the root page, so do the ** copy */ zeroPage(pPage, pChild->aData[0]); - resizeCellArray(pPage, pChild->nCell); for(i=0; inCell; i++){ - insertCell(pPage, i, pChild->aCell[i], - cellSize(pChild, pChild->aCell[i]), 0); + szCell[i] = cellSize(pChild, pChild->aCell[i]); } + assemblePage(pPage, pChild->nCell, pChild->aCell, szCell); freePage(pChild); TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno)); }else{ @@ -3121,11 +3201,8 @@ static int balance(MemPage *pPage){ MemPage *pNew = apNew[i]; assert( pNew->pgno==pgnoNew[i] ); resizeCellArray(pNew, cntNew[i] - j); - while( jnFree>=szCell[j] ); - insertCell(pNew, pNew->nCell, apCell[j], szCell[j], 0); - j++; - } + assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]); + j = cntNew[i]; assert( pNew->nCell>0 ); assert( !pNew->isOverfull ); relinkCellList(pNew); @@ -3305,6 +3382,7 @@ int sqlite3BtreeInsert( }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); pCur->idx++; + pCur->infoValid = 0; }else{ assert( pPage->leaf ); } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e33ad0e5ee..11a7ba7e67 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1290,7 +1290,7 @@ int sqlite3VdbeSerialGet(const unsigned char *buf, u64 serial_type, Mem *pMem){ len = sqlite3VdbeSerialTypeLen(serial_type); pMem->n = len; if( len>NBFS ){ - pMem->z = sqliteMalloc( len ); + pMem->z = sqliteMallocRaw( len ); if( !pMem->z ){ return -1; }