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

Make cellSizePtr() a method on the MemPage object, with alternative

implementations depending on the page type.  This results is a small performance
improvement and size reduction.

FossilOrigin-Name: 02f7e9d7d7b93d0b6bbd6cc0d0359b3b741b9931
This commit is contained in:
drh
2015-06-19 15:07:14 +00:00
parent 4307690b5c
commit 25ada07ab4
4 changed files with 59 additions and 31 deletions

View File

@@ -1,5 +1,5 @@
C Further\s#ifdef\schanges\sin\sspeedtest1.c\sin\sorder\sto\ssupport\sSQLite\sback\sto\nversion\s3.3.9\sand\sperhaps\seven\searlier. C Make\scellSizePtr()\sa\smethod\son\sthe\sMemPage\sobject,\swith\salternative\nimplementations\sdepending\son\sthe\spage\stype.\s\sThis\sresults\sis\sa\ssmall\sperformance\nimprovement\sand\ssize\sreduction.
D 2015-06-18T15:26:09.205 D 2015-06-19T15:07:14.566
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 1063c58075b7400d93326b0eb332b48a54f53025 F Makefile.in 1063c58075b7400d93326b0eb332b48a54f53025
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -192,9 +192,9 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3 F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c 02caf39192ed1f5c7157a1aac0b2ff23389233de F src/btree.c 960e66f4a9fd494c5712f4342432a2fb1cbb72c1
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4 F src/btreeInt.h 97901d5434a22344cd5ae47e80ed677bd21d572d
F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70 F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575 F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
@@ -1286,7 +1286,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P ed96e14adce4a4f94cc6838c46bc97937c4cb72a P 9246eca54adaee571dab0c066afaa604fcf9c44f
R 4e77e4d1b1f5f9af9315f930f1585b67 R 65525ba5a493bb8d3d370265d6f2abe8
U drh U drh
Z 4a2d5290228b5807450e51ccee479c2e Z b80278f806bcab0592c2162609b43f46

View File

@@ -1 +1 @@
9246eca54adaee571dab0c066afaa604fcf9c44f 02f7e9d7d7b93d0b6bbd6cc0d0359b3b741b9931

View File

@@ -1065,6 +1065,11 @@ static void btreeParseCell(
** data area of the btree-page. The return number includes the cell ** data area of the btree-page. The return number includes the cell
** data header and the local payload, but not any overflow page or ** data header and the local payload, but not any overflow page or
** the space used by the cell pointer. ** the space used by the cell pointer.
**
** The first implementation, cellSizePtr(), handles pages that contain
** payload, which is to say all index pages and left table pages. The
** second cellSizePtrNoPayload() implemention is a high-speed version
** for pages that contain no payload - internal table pages.
*/ */
static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */ u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */
@@ -1080,12 +1085,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
btreeParseCellPtr(pPage, pCell, &debuginfo); btreeParseCellPtr(pPage, pCell, &debuginfo);
#endif #endif
if( pPage->noPayload ){ assert( pPage->noPayload==0 );
pEnd = &pIter[9];
while( (*pIter++)&0x80 && pIter<pEnd );
assert( pPage->childPtrSize==4 );
return (u16)(pIter - pCell);
}
nSize = *pIter; nSize = *pIter;
if( nSize>=0x80 ){ if( nSize>=0x80 ){
pEnd = &pIter[9]; pEnd = &pIter[9];
@@ -1120,12 +1120,32 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
assert( nSize==debuginfo.nSize || CORRUPT_DB ); assert( nSize==debuginfo.nSize || CORRUPT_DB );
return (u16)nSize; return (u16)nSize;
} }
static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){
u8 *pIter = pCell + 4; /* For looping over bytes of pCell */
u8 *pEnd; /* End mark for a varint */
#ifdef SQLITE_DEBUG
/* The value returned by this function should always be the same as
** the (CellInfo.nSize) value found by doing a full parse of the
** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
** this function verifies that this invariant is not violated. */
CellInfo debuginfo;
btreeParseCellPtr(pPage, pCell, &debuginfo);
#endif
assert( pPage->childPtrSize==4 );
pEnd = pIter + 9;
while( (*pIter++)&0x80 && pIter<pEnd );
assert( debuginfo.nSize==(u16)(pIter - pCell) || CORRUPT_DB );
return (u16)(pIter - pCell);
}
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
/* This variation on cellSizePtr() is used inside of assert() statements /* This variation on cellSizePtr() is used inside of assert() statements
** only. */ ** only. */
static u16 cellSize(MemPage *pPage, int iCell){ static u16 cellSize(MemPage *pPage, int iCell){
return cellSizePtr(pPage, findCell(pPage, iCell)); return pPage->xCellSize(pPage, findCell(pPage, iCell));
} }
#endif #endif
@@ -1203,7 +1223,7 @@ static int defragmentPage(MemPage *pPage){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
} }
assert( pc>=iCellFirst && pc<=iCellLast ); assert( pc>=iCellFirst && pc<=iCellLast );
size = cellSizePtr(pPage, &src[pc]); size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size; cbrk -= size;
if( cbrk<iCellFirst || pc+size>usableSize ){ if( cbrk<iCellFirst || pc+size>usableSize ){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
@@ -1507,6 +1527,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 ); pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
flagByte &= ~PTF_LEAF; flagByte &= ~PTF_LEAF;
pPage->childPtrSize = 4-4*pPage->leaf; pPage->childPtrSize = 4-4*pPage->leaf;
pPage->xCellSize = cellSizePtr;
pBt = pPage->pBt; pBt = pPage->pBt;
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
/* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior /* EVIDENCE-OF: R-03640-13415 A value of 5 means the page is an interior
@@ -1516,8 +1537,14 @@ static int decodeFlags(MemPage *pPage, int flagByte){
** table b-tree page. */ ** table b-tree page. */
assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 ); assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
pPage->intKey = 1; pPage->intKey = 1;
pPage->intKeyLeaf = pPage->leaf; if( pPage->leaf ){
pPage->noPayload = !pPage->leaf; pPage->intKeyLeaf = 1;
pPage->noPayload = 0;
}else{
pPage->intKeyLeaf = 0;
pPage->noPayload = 1;
pPage->xCellSize = cellSizePtrNoPayload;
}
pPage->maxLocal = pBt->maxLeaf; pPage->maxLocal = pBt->maxLeaf;
pPage->minLocal = pBt->minLeaf; pPage->minLocal = pBt->minLeaf;
}else if( flagByte==PTF_ZERODATA ){ }else if( flagByte==PTF_ZERODATA ){
@@ -1624,7 +1651,7 @@ static int btreeInitPage(MemPage *pPage){
if( pc<iCellFirst || pc>iCellLast ){ if( pc<iCellFirst || pc>iCellLast ){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
} }
sz = cellSizePtr(pPage, &data[pc]); sz = pPage->xCellSize(pPage, &data[pc]);
testcase( pc+sz==usableSize ); testcase( pc+sz==usableSize );
if( pc+sz>usableSize ){ if( pc+sz>usableSize ){
return SQLITE_CORRUPT_BKPT; return SQLITE_CORRUPT_BKPT;
@@ -6096,7 +6123,7 @@ static void insertCell(
** wanted to be less than 4 but got rounded up to 4 on the leaf, then size ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
** might be less than 8 (leaf-size + pointer) on the interior node. Hence ** might be less than 8 (leaf-size + pointer) on the interior node. Hence
** the term after the || in the following assert(). */ ** the term after the || in the following assert(). */
assert( sz==cellSizePtr(pPage, pCell) || (sz==8 && iChild>0) ); assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pPage->nOverflow || sz+2>pPage->nFree ){
if( pTemp ){ if( pTemp ){
memcpy(pTemp, pCell, sz); memcpy(pTemp, pCell, sz);
@@ -6187,8 +6214,8 @@ static void rebuildPage(
memcpy(pData, pCell, szCell[i]); memcpy(pData, pCell, szCell[i]);
put2byte(pCellptr, (pData - aData)); put2byte(pCellptr, (pData - aData));
pCellptr += 2; pCellptr += 2;
assert( szCell[i]==cellSizePtr(pPg, pCell) || CORRUPT_DB ); assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
testcase( szCell[i]==cellSizePtr(pPg,pCell) ); testcase( szCell[i]==pPg->xCellSize(pPg,pCell) );
} }
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */ /* The pPg->nFree field is now set incorrectly. The caller will fix it. */
@@ -6478,7 +6505,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
u8 *pOut = &pSpace[4]; u8 *pOut = &pSpace[4];
u8 *pCell = pPage->apOvfl[0]; u8 *pCell = pPage->apOvfl[0];
u16 szCell = cellSizePtr(pPage, pCell); u16 szCell = pPage->xCellSize(pPage, pCell);
u8 *pStop; u8 *pStop;
assert( sqlite3PagerIswriteable(pNew->pDbPage) ); assert( sqlite3PagerIswriteable(pNew->pDbPage) );
@@ -6784,12 +6811,12 @@ static int balance_nonroot(
if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){ if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){
apDiv[i] = pParent->apOvfl[0]; apDiv[i] = pParent->apOvfl[0];
pgno = get4byte(apDiv[i]); pgno = get4byte(apDiv[i]);
szNew[i] = cellSizePtr(pParent, apDiv[i]); szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
pParent->nOverflow = 0; pParent->nOverflow = 0;
}else{ }else{
apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow); apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow);
pgno = get4byte(apDiv[i]); pgno = get4byte(apDiv[i]);
szNew[i] = cellSizePtr(pParent, apDiv[i]); szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
/* Drop the cell from the parent page. apDiv[i] still points to /* Drop the cell from the parent page. apDiv[i] still points to
** the cell within the parent, even though it has been dropped. ** the cell within the parent, even though it has been dropped.
@@ -6879,7 +6906,7 @@ static int balance_nonroot(
for(j=0; j<limit; j++){ for(j=0; j<limit; j++){
assert( nCell<nMaxCells ); assert( nCell<nMaxCells );
apCell[nCell] = findOverflowCell(pOld, j); apCell[nCell] = findOverflowCell(pOld, j);
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]); szCell[nCell] = pOld->xCellSize(pOld, apCell[nCell]);
nCell++; nCell++;
} }
}else{ }else{
@@ -6889,7 +6916,7 @@ static int balance_nonroot(
for(j=0; j<limit; j++){ for(j=0; j<limit; j++){
assert( nCell<nMaxCells ); assert( nCell<nMaxCells );
apCell[nCell] = findCellv2(aData, maskPage, cellOffset, j); apCell[nCell] = findCellv2(aData, maskPage, cellOffset, j);
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]); szCell[nCell] = pOld->xCellSize(pOld, apCell[nCell]);
nCell++; nCell++;
} }
} }
@@ -7207,7 +7234,7 @@ static int balance_nonroot(
*/ */
if( szCell[j]==4 ){ if( szCell[j]==4 ){
assert(leafCorrection==4); assert(leafCorrection==4);
sz = cellSizePtr(pParent, pCell); sz = pParent->xCellSize(pParent, pCell);
} }
} }
iOvflSpace += sz; iOvflSpace += sz;
@@ -7652,7 +7679,7 @@ int sqlite3BtreeInsert(
assert( newCell!=0 ); assert( newCell!=0 );
rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
if( rc ) goto end_insert; if( rc ) goto end_insert;
assert( szNew==cellSizePtr(pPage, newCell) ); assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) ); assert( szNew <= MX_CELL_SIZE(pBt) );
idx = pCur->aiIdx[pCur->iPage]; idx = pCur->aiIdx[pCur->iPage];
if( loc==0 ){ if( loc==0 ){
@@ -7794,7 +7821,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
pCell = findCell(pLeaf, pLeaf->nCell-1); pCell = findCell(pLeaf, pLeaf->nCell-1);
if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT; if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
nCell = cellSizePtr(pLeaf, pCell); nCell = pLeaf->xCellSize(pLeaf, pCell);
assert( MX_CELL_SIZE(pBt) >= nCell ); assert( MX_CELL_SIZE(pBt) >= nCell );
pTmp = pBt->pTmpSpace; pTmp = pBt->pTmpSpace;
assert( pTmp!=0 ); assert( pTmp!=0 );
@@ -8806,7 +8833,7 @@ static int checkTreePage(
int pc = get2byte(&data[cellStart+i*2]); int pc = get2byte(&data[cellStart+i*2]);
u32 size = 65536; u32 size = 65536;
if( pc<=usableSize-4 ){ if( pc<=usableSize-4 ){
size = cellSizePtr(pPage, &data[pc]); size = pPage->xCellSize(pPage, &data[pc]);
} }
if( (int)(pc+size-1)>=usableSize ){ if( (int)(pc+size-1)>=usableSize ){
pCheck->zPfx = 0; pCheck->zPfx = 0;

View File

@@ -295,6 +295,7 @@ struct MemPage {
u8 *aDataEnd; /* One byte past the end of usable data */ u8 *aDataEnd; /* One byte past the end of usable data */
u8 *aCellIdx; /* The cell index area */ u8 *aCellIdx; /* The cell index area */
DbPage *pDbPage; /* Pager page handle */ DbPage *pDbPage; /* Pager page handle */
u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */
Pgno pgno; /* Page number for this page */ Pgno pgno; /* Page number for this page */
}; };