]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Attempt to further reduce memcpy() in balance_nonroot().
authordan <dan@noemail.net>
Sat, 11 Oct 2014 20:00:24 +0000 (20:00 +0000)
committerdan <dan@noemail.net>
Sat, 11 Oct 2014 20:00:24 +0000 (20:00 +0000)
FossilOrigin-Name: fec849dcca3aead2bc2d4ecffeda750684d32fb0

manifest
manifest.uuid
src/btree.c

index aeefa53238e6e693bbcde97edda3620f16df7ab2..7e782aa82c81ba1bb771863452de787b20a0a262 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index bb422fd7dd5206e0947064a1098829fdbf8a977b..006b3c0008152a21bf0096cf81a0e0dd4018f84c 100644 (file)
@@ -1 +1 @@
-29304499ea4b72dbb6701e10cc19b5d41f7e5ac9
\ No newline at end of file
+fec849dcca3aead2bc2d4ecffeda750684d32fb0
\ No newline at end of file
index dbf002ecdbf4105bc250dee77de946e875b8a5cf..13ec9127480d1f671d90f9d2b750b6889387beea 100644 (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) 
     );