/ Changes On Branch failed-dropCell-opt
Login

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

Changes In Branch failed-dropCell-opt Excluding Merge-Ins

This is equivalent to a diff from 684ef4582e to 478627c9e9

2016-12-10
04:06
Avoid signed integer overflow when dealing with a LIMIT and OFFSET whose sum exceeds the maximum integer value. (check-in: c9bdf7adb4 user: drh tags: trunk)
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: 478627c9e9 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: 684ef4582e user: drh tags: trunk)
18:09
Additional comments and an assert on the sqlite3BtreeInsert() overwrite optimization. (check-in: c1f0ae9d29 user: drh tags: trunk)

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
  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








|
>
>
>
>





>
>







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
  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

7114
7115
7116
7117
7118
7119
7120





7121
7122
7123
7124
7125
7126
7127
7128
          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;








>
>
>
>
>
|







7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
          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;

7582
7583
7584
7585
7586
7587
7588





















7589

7590
7591
7592


7593
7594
7595
7596
7597
7598
7599
        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







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



>
>







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
        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