1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +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

@@ -1065,6 +1065,11 @@ static void btreeParseCell(
** data area of the btree-page. The return number includes the cell
** data header and the local payload, but not any overflow page or
** 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){
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);
#endif
if( pPage->noPayload ){
pEnd = &pIter[9];
while( (*pIter++)&0x80 && pIter<pEnd );
assert( pPage->childPtrSize==4 );
return (u16)(pIter - pCell);
}
assert( pPage->noPayload==0 );
nSize = *pIter;
if( nSize>=0x80 ){
pEnd = &pIter[9];
@@ -1120,12 +1120,32 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
assert( nSize==debuginfo.nSize || CORRUPT_DB );
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
/* This variation on cellSizePtr() is used inside of assert() statements
** only. */
static u16 cellSize(MemPage *pPage, int iCell){
return cellSizePtr(pPage, findCell(pPage, iCell));
return pPage->xCellSize(pPage, findCell(pPage, iCell));
}
#endif
@@ -1203,7 +1223,7 @@ static int defragmentPage(MemPage *pPage){
return SQLITE_CORRUPT_BKPT;
}
assert( pc>=iCellFirst && pc<=iCellLast );
size = cellSizePtr(pPage, &src[pc]);
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
if( cbrk<iCellFirst || pc+size>usableSize ){
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 );
flagByte &= ~PTF_LEAF;
pPage->childPtrSize = 4-4*pPage->leaf;
pPage->xCellSize = cellSizePtr;
pBt = pPage->pBt;
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
/* 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. */
assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
pPage->intKey = 1;
pPage->intKeyLeaf = pPage->leaf;
pPage->noPayload = !pPage->leaf;
if( pPage->leaf ){
pPage->intKeyLeaf = 1;
pPage->noPayload = 0;
}else{
pPage->intKeyLeaf = 0;
pPage->noPayload = 1;
pPage->xCellSize = cellSizePtrNoPayload;
}
pPage->maxLocal = pBt->maxLeaf;
pPage->minLocal = pBt->minLeaf;
}else if( flagByte==PTF_ZERODATA ){
@@ -1624,7 +1651,7 @@ static int btreeInitPage(MemPage *pPage){
if( pc<iCellFirst || pc>iCellLast ){
return SQLITE_CORRUPT_BKPT;
}
sz = cellSizePtr(pPage, &data[pc]);
sz = pPage->xCellSize(pPage, &data[pc]);
testcase( pc+sz==usableSize );
if( pc+sz>usableSize ){
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
** might be less than 8 (leaf-size + pointer) on the interior node. Hence
** 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( pTemp ){
memcpy(pTemp, pCell, sz);
@@ -6187,8 +6214,8 @@ static void rebuildPage(
memcpy(pData, pCell, szCell[i]);
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
assert( szCell[i]==cellSizePtr(pPg, pCell) || CORRUPT_DB );
testcase( szCell[i]==cellSizePtr(pPg,pCell) );
assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
testcase( szCell[i]==pPg->xCellSize(pPg,pCell) );
}
/* 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 *pCell = pPage->apOvfl[0];
u16 szCell = cellSizePtr(pPage, pCell);
u16 szCell = pPage->xCellSize(pPage, pCell);
u8 *pStop;
assert( sqlite3PagerIswriteable(pNew->pDbPage) );
@@ -6784,12 +6811,12 @@ static int balance_nonroot(
if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){
apDiv[i] = pParent->apOvfl[0];
pgno = get4byte(apDiv[i]);
szNew[i] = cellSizePtr(pParent, apDiv[i]);
szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
pParent->nOverflow = 0;
}else{
apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow);
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
** 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++){
assert( nCell<nMaxCells );
apCell[nCell] = findOverflowCell(pOld, j);
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
szCell[nCell] = pOld->xCellSize(pOld, apCell[nCell]);
nCell++;
}
}else{
@@ -6889,7 +6916,7 @@ static int balance_nonroot(
for(j=0; j<limit; j++){
assert( nCell<nMaxCells );
apCell[nCell] = findCellv2(aData, maskPage, cellOffset, j);
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
szCell[nCell] = pOld->xCellSize(pOld, apCell[nCell]);
nCell++;
}
}
@@ -7207,7 +7234,7 @@ static int balance_nonroot(
*/
if( szCell[j]==4 ){
assert(leafCorrection==4);
sz = cellSizePtr(pParent, pCell);
sz = pParent->xCellSize(pParent, pCell);
}
}
iOvflSpace += sz;
@@ -7652,7 +7679,7 @@ int sqlite3BtreeInsert(
assert( newCell!=0 );
rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
if( rc ) goto end_insert;
assert( szNew==cellSizePtr(pPage, newCell) );
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
idx = pCur->aiIdx[pCur->iPage];
if( loc==0 ){
@@ -7794,7 +7821,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
pCell = findCell(pLeaf, pLeaf->nCell-1);
if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
nCell = cellSizePtr(pLeaf, pCell);
nCell = pLeaf->xCellSize(pLeaf, pCell);
assert( MX_CELL_SIZE(pBt) >= nCell );
pTmp = pBt->pTmpSpace;
assert( pTmp!=0 );
@@ -8806,7 +8833,7 @@ static int checkTreePage(
int pc = get2byte(&data[cellStart+i*2]);
u32 size = 65536;
if( pc<=usableSize-4 ){
size = cellSizePtr(pPage, &data[pc]);
size = pPage->xCellSize(pPage, &data[pc]);
}
if( (int)(pc+size-1)>=usableSize ){
pCheck->zPfx = 0;