SQLite

Check-in [badd0873e6]
Login

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

Overview
Comment:Performance improvements in getAndInitPage(): omit the upper bound check on page number if the page is already in cache. (CVS 5716)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: badd0873e6dffac9463b06a381b9f797a54d33e9
User & Date: drh 2008-09-18 01:08:16.000
Context
2008-09-18
11:18
Changes to test script io.test to work on symbian. (CVS 5717) (check-in: 2b41c4959d user: danielk1977 tags: trunk)
01:08
Performance improvements in getAndInitPage(): omit the upper bound check on page number if the page is already in cache. (CVS 5716) (check-in: badd0873e6 user: drh tags: trunk)
2008-09-17
20:06
Speed improvements for in-memory databases by omitting flag clearing on pages where it is impossible for the flag to be set and by avoiding assert()s on non-debugging builds. Ticket #3384. (CVS 5715) (check-in: a7fd9e622b user: drh tags: trunk)
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to src/btree.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
19











-
+







/*
** 2004 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.511 2008/09/10 17:53:36 danielk1977 Exp $
** $Id: btree.c,v 1.512 2008/09/18 01:08:16 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
#include "btreeInt.h"

1047
1048
1049
1050
1051
1052
1053















1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084

1085
1086
1087
1088
1089
1090
1091
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090
1091







1092
1093
1094
1095
1096
1097
1098
1099







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















-





-
-
-
-
-
-
-
+







  assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
  pPage->maskPage = pBt->pageSize - 1;
  pPage->idxShift = 0;
  pPage->nCell = 0;
  pPage->isInit = 1;
}


/*
** Convert a DbPage obtained from the pager into a MemPage used by
** the btree layer.
*/
static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
  MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
  pPage->aData = sqlite3PagerGetData(pDbPage);
  pPage->pDbPage = pDbPage;
  pPage->pBt = pBt;
  pPage->pgno = pgno;
  pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
  return pPage; 
}

/*
** Get a page from the pager.  Initialize the MemPage.pBt and
** MemPage.aData elements if needed.
**
** If the noContent flag is set, it means that we do not care about
** the content of the page at this time.  So do not go to the disk
** to fetch the content.  Just fill in the content with zeros for now.
** If in the future we call sqlite3PagerWrite() on this page, that
** means we have started to be concerned about content and the disk
** read should occur at that point.
*/
int sqlite3BtreeGetPage(
  BtShared *pBt,       /* The btree */
  Pgno pgno,           /* Number of the page to fetch */
  MemPage **ppPage,    /* Return the page in this parameter */
  int noContent        /* Do not load page content if true */
){
  int rc;
  MemPage *pPage;
  DbPage *pDbPage;

  assert( sqlite3_mutex_held(pBt->mutex) );
  rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
  if( rc ) return rc;
  pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage);
  pPage->aData = sqlite3PagerGetData(pDbPage);
  pPage->pDbPage = pDbPage;
  pPage->pBt = pBt;
  pPage->pgno = pgno;
  pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
  *ppPage = pPage;
  *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
  return SQLITE_OK;
}

/*
** Return the size of the database file in pages.  Or return -1 if
** there is any kind of error.
*/
1104
1105
1106
1107
1108
1109
1110



1111
1112
















1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130




















1131
1132
1133
1134
1135
1136
1137
1138
1139
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139


















1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159


1160
1161
1162
1163
1164
1165
1166







+
+
+


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-







static int getAndInitPage(
  BtShared *pBt,          /* The database file */
  Pgno pgno,           /* Number of the page to get */
  MemPage **ppPage,    /* Write the page pointer here */
  MemPage *pParent     /* Parent of the page */
){
  int rc;
  DbPage *pDbPage;
  MemPage *pPage;

  assert( sqlite3_mutex_held(pBt->mutex) );
  assert( !pParent || pParent->isInit );
  if( pgno==0 ){
    return SQLITE_CORRUPT_BKPT; 
  }

  /* It is often the case that the page we want is already in cache.
  ** If so, get it directly.  This saves us from having to call
  ** pagerPagecount() to make sure pgno is within limits, which results
  ** in a measureable performance improvements.
  */
  pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
  if( pDbPage ){
    /* Page is already in cache */
    *ppPage = pPage = btreePageFromDbPage(pDbPage, pgno, pBt);
    rc = SQLITE_OK;
  }else{
    /* Page not in cache.  Acquire it. */
  if( pgno==0 || pgno>pagerPagecount(pBt->pPager) ){
    return SQLITE_CORRUPT_BKPT; 
  }
  rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
  if( rc==SQLITE_OK ){
    if( (*ppPage)->isInit==0 ){
      rc = sqlite3BtreeInitPage(*ppPage, pParent);
    }else if( pParent && ((*ppPage)==pParent || (*ppPage)->pParent!=pParent) ){
      /* This condition indicates a loop in the b-tree structure (the scenario
      ** where database corruption has caused a page to be a direct or
      ** indirect descendant of itself).
      */ 
      rc = SQLITE_CORRUPT_BKPT;
    }
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
      *ppPage = 0;
    }
    if( pgno>pagerPagecount(pBt->pPager) ){
      return SQLITE_CORRUPT_BKPT; 
    }
    rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
    if( rc ) return rc;
    pPage = *ppPage;
  }
  if( pPage->isInit==0 ){
     rc = sqlite3BtreeInitPage(pPage, pParent);
  }else if( pParent && (pPage==pParent || pPage->pParent!=pParent) ){
    /* This condition indicates a loop in the b-tree structure (the scenario
    ** where database corruption has caused a page to be a direct or
    ** indirect descendant of itself).
    */ 
    rc = SQLITE_CORRUPT_BKPT;
  }
  if( rc!=SQLITE_OK ){
    releasePage(pPage);
    *ppPage = 0;
  }
  }

  return rc;
}

/*
** Release a MemPage.  This should be called once for each prior
** call to sqlite3BtreeGetPage.
*/