Attempt to further reduce memcpy() in balance_nonroot().

FossilOrigin-Name: fec849dcca3aead2bc2d4ecffeda750684d32fb0
This commit is contained in:
dan
2014-10-11 20:00:24 +00:00
parent 33ea486603
commit 09c6840153
3 changed files with 179 additions and 20 deletions
+6 -6
View File
@@ -1,5 +1,5 @@
C Change\sthe\sbalance_nonroot()\sroutine\sto\sreduce\sthe\samount\sof\smemcpy\swork\sthat\stakes\splace.\sThis\sis\sa\swork\sin\sprogress.
D 2014-10-09T19:35:37.452
C Attempt\sto\sfurther\sreduce\smemcpy()\sin\sbalance_nonroot().
D 2014-10-11T20:00:24.552
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -172,7 +172,7 @@ F src/auth.c d8abcde53426275dab6243b441256fcd8ccbebb2
F src/backup.c a31809c65623cc41849b94d368917f8bb66e6a7e
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
F src/btree.c 7b89fde3bffa5b7300e94c4aeb69ccff926ef513
F src/btree.c d5f4f74e309f79ace4b4025c433874ead635bed2
F src/btree.h a79aa6a71e7f1055f01052b7f821bd1c2dce95c8
F src/btreeInt.h 1bd7957161a1346a914f1f09231610e777a8e58d
F src/build.c bde83dd5cf812e310a7e5ad2846790a14745bef4
@@ -1200,7 +1200,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 3edab9957cc7bb90b52fd40b02613c2cb03fc166
R 5fca1836b5a4d862df24682ecb47d048
P 29304499ea4b72dbb6701e10cc19b5d41f7e5ac9
R 3235ac37769ff059d7c714947e8a11dd
U dan
Z 8527330c8f275358262176fc962502e2
Z 17fdfd7faf788bbb79d2ec9941c17025
+1 -1
View File
@@ -1 +1 @@
29304499ea4b72dbb6701e10cc19b5d41f7e5ac9
fec849dcca3aead2bc2d4ecffeda750684d32fb0
+172 -13
View File
@@ -5980,10 +5980,9 @@ static void assemblePage(
static void rebuildPage(
MemPage *pPg, /* Edit this page */
int nRemove, /* Cells to remove from start of page */
int nCell, /* Final number of cells on page */
u8 **apCell, /* Array of nCell final cells */
u16 *szCell /* Array of nCell cell sizes */
u8 **apCell, /* Array of cells */
u16 *szCell /* Array of cell sizes */
){
const int hdr = pPg->hdrOffset; /* Offset of header on pPg */
u8 * const aData = pPg->aData; /* Pointer to data for pPg */
@@ -6020,6 +6019,129 @@ static void rebuildPage(
aData[hdr+7] = 0x00;
}
static void editPage(
MemPage *pPg, /* Edit this page */
int iOld, /* Index of first cell currently on page */
int iNew, /* Index of new first cell on page */
int nNew, /* Final number of cells on page */
u8 **apCell, /* Array of cells */
u16 *szCell /* Array of cell sizes */
){
if( 1 ){
u8 * const aData = pPg->aData;
const int hdr = pPg->hdrOffset;
u8 *pBegin = &pPg->aCellIdx[nNew * 2];
int nFree = pPg->nFree; /* Free bytes on pPg */
int nCell = pPg->nCell; /* Cells stored on pPg */
u8 *pData;
u8 *pCellptr;
int i;
int iOldEnd = iOld + pPg->nCell + pPg->nOverflow;
#ifdef SQLITE_DEBUG
u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
memcpy(pTmp, aData, pPg->pBt->usableSize);
#endif
/* Remove cells from the start and end of the page */
if( iOld<iNew ){
int nShift = 0;
for(i=iOld; i<iNew; i++){
if( apCell[i]>aData && apCell[i]<&aData[pPg->pBt->usableSize] ){
freeSpace(pPg, apCell[i] - aData, szCell[i]);
nFree += szCell[i] + 2;
nShift++;
}
}
nCell -= nShift;
memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
}
for(i=iNew+nNew; i<iOldEnd; i++){
if( apCell[i]>aData && apCell[i]<&aData[pPg->pBt->usableSize] ){
freeSpace(pPg, apCell[i] - aData, szCell[i]);
nFree += szCell[i] + 2;
nCell--;
}
}
pData = &aData[get2byte(&aData[hdr+5])];
if( pData<pBegin ) goto editpage_fail;
/* Add cells to the start of the page */
if( iNew<iOld ){
pCellptr = pPg->aCellIdx;
memmove(&pCellptr[(iOld-iNew)*2], pCellptr, nCell*2);
for(i=iNew; i<iOld; i++){
pData -= szCell[i];
if( pData<pBegin ) goto editpage_fail;
memcpy(pData, apCell[i], szCell[i]);
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
nFree -= (szCell[i] + 2);
nCell++;
}
}
/* Add any overflow cells */
for(i=0; i<pPg->nOverflow; i++){
int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
if( iCell>=0 && iCell<nNew ){
u8 *pCellptr = &pPg->aCellIdx[iCell * 2];
int sz = szCell[iCell+iNew];
memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
pData -= sz;
if( pData<pBegin ) goto editpage_fail;
memcpy(pData, apCell[iCell+iNew], sz);
put2byte(pCellptr, (pData - aData));
nFree -= (sz + 2);
nCell++;
}
}
/* Append cells to the end of the page */
pCellptr = &pPg->aCellIdx[nCell*2];
for(i=iNew+nCell; i<(iNew+nNew); i++){
pData -= szCell[i];
if( pData<pBegin ) goto editpage_fail;
memcpy(pData, apCell[i], szCell[i]);
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
nFree -= (szCell[i] + 2);
}
pPg->nFree = nFree;
pPg->nCell = nNew;
pPg->nOverflow = 0;
put2byte(&aData[hdr+3], pPg->nCell);
put2byte(&aData[hdr+5], pData - aData);
#ifdef SQLITE_DEBUG
for(i=0; i<nNew; i++){
u8 *pCell = apCell[i+iNew];
int iOff = get2byte(&pPg->aCellIdx[i*2]);
if( pCell>=aData && pCell<&aData[pPg->pBt->usableSize] ){
pCell = &pTmp[pCell - aData];
}
assert( 0==memcmp(pCell, &aData[iOff], szCell[i+iNew]) );
}
#endif
#if 0
printf("EDIT\n");
#endif
return;
}
editpage_fail:
#if 0
printf("REBUILD\n");
#endif
/* Unable to edit this page. Rebuild it from scratch instead. */
rebuildPage(pPg, nNew, &apCell[iNew], &szCell[iNew]);
}
/*
** The following parameters determine how many adjacent pages get involved
** in a balancing operation. NN is the number of neighbors on either side
@@ -6312,6 +6434,7 @@ static int balance_nonroot(
u8 *pRight; /* Location in parent of right-sibling pointer */
u8 *apDiv[NB-1]; /* Divider cells in pParent */
int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */
int cntOld[NB+2]; /* Old index in aCell[] after i-th page */
int szNew[NB+2]; /* Combined size of cells place on i-th page */
u8 **apCell = 0; /* All cells begin balanced */
u16 *szCell; /* Local size of all cells in apCell[] */
@@ -6487,6 +6610,7 @@ static int balance_nonroot(
nCell++;
}
}
cntOld[i] = nCell;
if( i<nOld-1 && !leafData){
u16 sz = (u16)szNew[i];
u8 *pTemp;
@@ -6624,6 +6748,7 @@ static int balance_nonroot(
zeroPage(pNew, pageFlags);
apNew[i] = pNew;
nNew++;
cntOld[i] = nCell;
/* Set the pointer-map entry for the new sibling page. */
if( ISAUTOVACUUM ){
@@ -6693,6 +6818,33 @@ static int balance_nonroot(
** to the apCell[] index of the first cell that will appear on the
** page following this balancing operation. */
int iFirst = (i==0 ? 0 : cntNew[i-1] + !leafData); /* new first cell */
#if 0
MemPage *pNew = apNew[i];
int iCell;
int nCta = 0;
int nFree;
printf("REBUILD %d: %d@%d -> %d@%d", apNew[i]->pgno,
pNew->nCell+pNew->nOverflow, j,
cntNew[i] - iFirst, iFirst
);
for(iCell=iFirst; iCell<cntNew[i]; iCell++){
if( apCell[iCell]<pNew->aData
|| apCell[iCell]>=&pNew->aData[pBt->usableSize]
){
nCta += szCell[iCell];
}
}
nFree = get2byte(&pNew->aData[pNew->hdrOffset+5]);
nFree -= (pNew->cellOffset + (cntNew[i] - iFirst) * 2);
printf(" cta=%d free=%d\n", nCta, nFree);
if( i==(nNew-1) ){
printf("-----\n");
fflush(stdout);
}
#endif
assert( i<nOld || j==nCell );
aShiftLeft[i] = j - iFirst;
j += apNew[i]->nCell + apNew[i]->nOverflow;
@@ -6835,17 +6987,23 @@ static int balance_nonroot(
&& (aShiftLeft[iPg]>=0 || abDone[iPg-1])
&& (aShiftRight[iPg]>=0 || abDone[iPg+1])
){
MemPage *pNew = apNew[iPg];
int iLeft = ((iPg==0) ? 0 : cntNew[iPg-1] + !leafData);
rebuildPage(pNew,
aShiftLeft[iPg] < 0 ? (aShiftLeft[iPg]*-1) : 0,
cntNew[iPg] - iLeft,
&apCell[iLeft],
&szCell[iLeft]
);
int iNew;
int iOld;
int nNewCell;
if( iPg==0 ){
iNew = iOld = 0;
nNewCell = cntNew[0];
}else{
iOld = iPg<nOld ? (cntOld[iPg-1] + !leafData) : nCell;
iNew = cntNew[iPg-1] + !leafData;
nNewCell = cntNew[iPg] - iNew;
}
editPage(apNew[iPg], iOld, iNew, nNewCell, apCell, szCell);
abDone[iPg] = 1;
assert( pNew->nOverflow==0 );
assert( pNew->nCell==(cntNew[iPg] - (iPg==0?0:cntNew[iPg-1]+!leafData)) );
assert( apNew[iPg]->nOverflow==0 );
assert( apNew[iPg]->nCell==nNewCell );
}
}
assert( memcmp(abDone, "\01\01\01\01\01", nNew)==0 );
@@ -6869,6 +7027,7 @@ static int balance_nonroot(
** is important if the parent page happens to be page 1 of the database
** image. */
assert( nNew==1 );
defragmentPage(apNew[0]);
assert( apNew[0]->nFree ==
(get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)
);