/ Check-in [478627c9]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:In balance_nonroot, try to combine dropCell/insertCell combinations for the dividers into a cell overwrites. This results in a very small (0.05%) performance gain which is probably not worth the added complexity.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | failed-dropCell-opt
Files: files | file ages | folders
SHA1:478627c9e949ffa97979cc91506b8c79a2aef484
User & Date: drh 2016-12-10 00:14:23
Context
2016-12-10
00:14
In balance_nonroot, try to combine dropCell/insertCell combinations for the dividers into a cell overwrites. This results in a very small (0.05%) performance gain which is probably not worth the added complexity. Closed-Leaf check-in: 478627c9 user: drh tags: failed-dropCell-opt
2016-12-09
19:42
When doing the sqlite3BtreeInsert() overwrite optimization, make sure the memcpy() does not extend off the end of the page. check-in: 684ef458 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

7013
7014
7015
7016
7017
7018
7019
7020




7021
7022
7023
7024
7025


7026
7027
7028
7029
7030
7031
7032
....
7114
7115
7116
7117
7118
7119
7120





7121
7122
7123
7124
7125
7126
7127
7128
....
7582
7583
7584
7585
7586
7587
7588





















7589

7590
7591
7592


7593
7594
7595
7596
7597
7598
7599
  int szNew[NB+2];             /* Combined size of cells placed on i-th page */
  u8 *aSpace1;                 /* Space for copies of dividers cells */
  Pgno pgno;                   /* Temp var to store a page number in */
  u8 abDone[NB+2];             /* True after i'th new page is populated */
  Pgno aPgno[NB+2];            /* Page numbers of new pages before shuffling */
  Pgno aPgOrder[NB+2];         /* Copy of aPgno[] used for sorting pages */
  u16 aPgFlags[NB+2];          /* flags field of new pages before shuffling */
  CellArray b;                  /* Parsed information on cells being balanced */





  memset(abDone, 0, sizeof(abDone));
  b.nCell = 0;
  b.apCell = 0;
  pBt = pParent->pBt;


  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( sqlite3PagerIswriteable(pParent->pDbPage) );

#if 0
  TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
#endif

................................................................................
          memset(apOld, 0, (i+1)*sizeof(MemPage*));
          goto balance_cleanup;
        }else{
          memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
          apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
        }
      }





      dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
    }
  }

  /* Make nMaxCells a multiple of 4 in order to preserve 8-byte
  ** alignment */
  nMaxCells = (nMaxCells + 3)&~3;

................................................................................
        assert(leafCorrection==4);
        sz = pParent->xCellSize(pParent, pCell);
      }
    }
    iOvflSpace += sz;
    assert( sz<=pBt->maxLocal+23 );
    assert( iOvflSpace <= (int)pBt->pageSize );





















    insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);

    if( rc!=SQLITE_OK ) goto balance_cleanup;
    assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  }



  /* Now update the actual sibling pages. The order in which they are updated
  ** is important, as this code needs to avoid disrupting any page from which
  ** cells may still to be read. In practice, this means:
  **
  **  (1) If cells are moving left (from apNew[iPg] to apNew[iPg-1])
  **      then it is not safe to update page apNew[iPg] until after







|
>
>
>
>





>
>







 







>
>
>
>
>
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>



>
>







7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
....
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
....
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
  int szNew[NB+2];             /* Combined size of cells placed on i-th page */
  u8 *aSpace1;                 /* Space for copies of dividers cells */
  Pgno pgno;                   /* Temp var to store a page number in */
  u8 abDone[NB+2];             /* True after i'th new page is populated */
  Pgno aPgno[NB+2];            /* Page numbers of new pages before shuffling */
  Pgno aPgOrder[NB+2];         /* Copy of aPgno[] used for sorting pages */
  u16 aPgFlags[NB+2];          /* flags field of new pages before shuffling */
  CellArray b;                 /* Parsed information on cells being balanced */
  struct DeferredDropCell {    /* Deferred calls to dropCell() for pParent */
     u16 idx;                     /* The index of the cell to drop */
     u16 sz;                      /* The size of the cell to drop */
  } sDDC0, sDDC1;              /* Up to 2 deferred calls */

  memset(abDone, 0, sizeof(abDone));
  b.nCell = 0;
  b.apCell = 0;
  pBt = pParent->pBt;
  sDDC0.sz = sDDC0.idx = 0;
  sDDC1.sz = sDDC1.idx = 0;
  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( sqlite3PagerIswriteable(pParent->pDbPage) );

#if 0
  TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
#endif

................................................................................
          memset(apOld, 0, (i+1)*sizeof(MemPage*));
          goto balance_cleanup;
        }else{
          memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
          apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
        }
      }
      assert( sDDC1.sz==0 );
      sDDC1 = sDDC0;
      sDDC0.idx = i+nxDiv-pParent->nOverflow;
      sDDC0.sz = szNew[i];
//printf("dropCell:\n");
//    dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
    }
  }

  /* Make nMaxCells a multiple of 4 in order to preserve 8-byte
  ** alignment */
  nMaxCells = (nMaxCells + 3)&~3;

................................................................................
        assert(leafCorrection==4);
        sz = pParent->xCellSize(pParent, pCell);
      }
    }
    iOvflSpace += sz;
    assert( sz<=pBt->maxLocal+23 );
    assert( iOvflSpace <= (int)pBt->pageSize );
    if( sDDC0.idx==nxDiv+i && sDDC0.sz==sz ){
      /* overwrite */
      unsigned char *oldCell = findCell(pParent, sDDC0.idx);
//printf("overwrite: pg=%d idx=%d sz=%d\n", pParent->pgno, sDDC0.idx, sDDC0.sz);
      memcpy(oldCell+4, pCell+4, sz-4);
      put4byte(oldCell, pNew->pgno);
      sDDC0 = sDDC1;
      sDDC1.sz = 0;
    }else{
      if( sDDC0.sz>0 ){
        if( sDDC1.sz>0 ){
//printf("dropCell: pg=%d idx=%d sz=%d\n", pParent->pgno, sDDC1.idx, sDDC1.sz);
          dropCell(pParent, sDDC1.idx, sDDC1.sz, &rc);
          sDDC1.sz = 0;
        }
//printf("dropCell: pg=%d idx=%d sz=%d\n", pParent->pgno, sDDC0.idx, sDDC0.sz);
        dropCell(pParent, sDDC0.idx, sDDC0.sz, &rc);
        sDDC0.sz = 0;
        if( rc ) goto balance_cleanup;
      }
//printf("insertCell: pg=%d idx=%d sz=%d\n", pParent->pgno, nxDiv+i, sz);
      insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
    }
    if( rc!=SQLITE_OK ) goto balance_cleanup;
    assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  }
  if( sDDC1.sz ) dropCell(pParent, sDDC1.idx, sDDC1.sz, &rc);
  if( sDDC0.sz ) dropCell(pParent, sDDC0.idx, sDDC0.sz, &rc);

  /* Now update the actual sibling pages. The order in which they are updated
  ** is important, as this code needs to avoid disrupting any page from which
  ** cells may still to be read. In practice, this means:
  **
  **  (1) If cells are moving left (from apNew[iPg] to apNew[iPg-1])
  **      then it is not safe to update page apNew[iPg] until after