mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Slightly smaller and faster code by encapsulating wal-index hash table
location information in a separate WalHashLoc object rather than passing around the various elements as separate variables. FossilOrigin-Name: 538a365b7a32ab7fa84f59d7556242cfb59b76d287b6417eb3a823197a354e8e
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
||||
C Improved\scomments\san\spresentation\sfor\sthe\srecent\sIN\soperator\sdecision\nimprovement.
|
||||
D 2018-06-09T14:13:46.495
|
||||
C Slightly\ssmaller\sand\sfaster\scode\sby\sencapsulating\swal-index\shash\stable\nlocation\sinformation\sin\sa\sseparate\sWalHashLoc\sobject\srather\sthan\spassing\naround\sthe\svarious\selements\sas\sseparate\svariables.
|
||||
D 2018-06-09T16:49:00.305
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
|
||||
@@ -576,7 +576,7 @@ F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2
|
||||
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
|
||||
F src/vtab.c 10ea07dec111de6fb0a4fc87a7ffa4c65fdc088a19dbfaf7d6f2b128f2e8eb7b
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0
|
||||
F src/wal.c d44a0811afd2155b1157c38b33141d4ac028fda6232485bed664015bb05819ca
|
||||
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
|
||||
F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
|
||||
F src/where.c fe1a6f97c12cc9472ccce86166ba3f827cf61d6ae770c036a6396b63863baac4
|
||||
@@ -1731,7 +1731,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P fd0934139076848f2f2edfd3d74d54608531031a05a60ca6ac1d7016dcd538df
|
||||
R b9ed4417ad4e47d1ad0ea2ffe1b71005
|
||||
P 31e480f68dfd887cfd9114f9f9fec53d751d3ecc27e36f55c0166b51b2fbb08c
|
||||
R 6ae6039dbf6c75d53dff2e4ab7fb3afb
|
||||
U drh
|
||||
Z fc8a0aeffe4e41486a64c0cdfcf48c75
|
||||
Z 6ec430bc7e585373e73f8d45e5d8a30b
|
||||
|
@@ -1 +1 @@
|
||||
31e480f68dfd887cfd9114f9f9fec53d751d3ecc27e36f55c0166b51b2fbb08c
|
||||
538a365b7a32ab7fa84f59d7556242cfb59b76d287b6417eb3a823197a354e8e
|
143
src/wal.c
143
src/wal.c
@@ -880,48 +880,51 @@ static int walNextHash(int iPriorHash){
|
||||
return (iPriorHash+1)&(HASHTABLE_NSLOT-1);
|
||||
}
|
||||
|
||||
/*
|
||||
** An instance of the WalHashLoc object is used to describe the location
|
||||
** of a page hash table in the wal-index. This becomes the return value
|
||||
** from walHashGet().
|
||||
*/
|
||||
typedef struct WalHashLoc WalHashLoc;
|
||||
struct WalHashLoc {
|
||||
volatile ht_slot *aHash; /* Start of the wal-index hash table */
|
||||
volatile u32 *aPgno; /* aPgno[1] is the page of first frame indexed */
|
||||
u32 iZero; /* One less than the frame number of first indexed*/
|
||||
};
|
||||
|
||||
/*
|
||||
** Return pointers to the hash table and page number array stored on
|
||||
** page iHash of the wal-index. The wal-index is broken into 32KB pages
|
||||
** numbered starting from 0.
|
||||
**
|
||||
** Set output variable *paHash to point to the start of the hash table
|
||||
** in the wal-index file. Set *piZero to one less than the frame
|
||||
** Set output variable pLoc->aHash to point to the start of the hash table
|
||||
** in the wal-index file. Set pLoc->iZero to one less than the frame
|
||||
** number of the first frame indexed by this hash table. If a
|
||||
** slot in the hash table is set to N, it refers to frame number
|
||||
** (*piZero+N) in the log.
|
||||
** (pLoc->iZero+N) in the log.
|
||||
**
|
||||
** Finally, set *paPgno so that *paPgno[1] is the page number of the
|
||||
** first frame indexed by the hash table, frame (*piZero+1).
|
||||
** Finally, set pLoc->aPgno so that pLoc->aPgno[1] is the page number of the
|
||||
** first frame indexed by the hash table, frame (pLoc->iZero+1).
|
||||
*/
|
||||
static int walHashGet(
|
||||
Wal *pWal, /* WAL handle */
|
||||
int iHash, /* Find the iHash'th table */
|
||||
volatile ht_slot **paHash, /* OUT: Pointer to hash index */
|
||||
volatile u32 **paPgno, /* OUT: Pointer to page number array */
|
||||
u32 *piZero /* OUT: Frame associated with *paPgno[0] */
|
||||
WalHashLoc *pLoc /* OUT: Hash table location */
|
||||
){
|
||||
int rc; /* Return code */
|
||||
volatile u32 *aPgno;
|
||||
|
||||
rc = walIndexPage(pWal, iHash, &aPgno);
|
||||
rc = walIndexPage(pWal, iHash, &pLoc->aPgno);
|
||||
assert( rc==SQLITE_OK || iHash>0 );
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
u32 iZero;
|
||||
volatile ht_slot *aHash;
|
||||
|
||||
aHash = (volatile ht_slot *)&aPgno[HASHTABLE_NPAGE];
|
||||
pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE];
|
||||
if( iHash==0 ){
|
||||
aPgno = &aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
|
||||
iZero = 0;
|
||||
pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
|
||||
pLoc->iZero = 0;
|
||||
}else{
|
||||
iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
|
||||
pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
|
||||
}
|
||||
|
||||
*paPgno = &aPgno[-1];
|
||||
*paHash = aHash;
|
||||
*piZero = iZero;
|
||||
pLoc->aPgno = &pLoc->aPgno[-1];
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -967,9 +970,7 @@ static u32 walFramePgno(Wal *pWal, u32 iFrame){
|
||||
** actually needed.
|
||||
*/
|
||||
static void walCleanupHash(Wal *pWal){
|
||||
volatile ht_slot *aHash = 0; /* Pointer to hash table to clear */
|
||||
volatile u32 *aPgno = 0; /* Page number array for hash table */
|
||||
u32 iZero = 0; /* frame == (aHash[x]+iZero) */
|
||||
WalHashLoc sLoc; /* Hash table location */
|
||||
int iLimit = 0; /* Zero values greater than this */
|
||||
int nByte; /* Number of bytes to zero in aPgno[] */
|
||||
int i; /* Used to iterate through aHash[] */
|
||||
@@ -987,24 +988,24 @@ static void walCleanupHash(Wal *pWal){
|
||||
*/
|
||||
assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
|
||||
assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
|
||||
walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &aHash, &aPgno, &iZero);
|
||||
walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
|
||||
|
||||
/* Zero all hash-table entries that correspond to frame numbers greater
|
||||
** than pWal->hdr.mxFrame.
|
||||
*/
|
||||
iLimit = pWal->hdr.mxFrame - iZero;
|
||||
iLimit = pWal->hdr.mxFrame - sLoc.iZero;
|
||||
assert( iLimit>0 );
|
||||
for(i=0; i<HASHTABLE_NSLOT; i++){
|
||||
if( aHash[i]>iLimit ){
|
||||
aHash[i] = 0;
|
||||
if( sLoc.aHash[i]>iLimit ){
|
||||
sLoc.aHash[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero the entries in the aPgno array that correspond to frames with
|
||||
** frame numbers greater than pWal->hdr.mxFrame.
|
||||
*/
|
||||
nByte = (int)((char *)aHash - (char *)&aPgno[iLimit+1]);
|
||||
memset((void *)&aPgno[iLimit+1], 0, nByte);
|
||||
nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit+1]);
|
||||
memset((void *)&sLoc.aPgno[iLimit+1], 0, nByte);
|
||||
|
||||
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
/* Verify that the every entry in the mapping region is still reachable
|
||||
@@ -1014,10 +1015,10 @@ static void walCleanupHash(Wal *pWal){
|
||||
int j; /* Loop counter */
|
||||
int iKey; /* Hash key */
|
||||
for(j=1; j<=iLimit; j++){
|
||||
for(iKey=walHash(aPgno[j]); aHash[iKey]; iKey=walNextHash(iKey)){
|
||||
if( aHash[iKey]==j ) break;
|
||||
for(iKey=walHash(sLoc.aPgno[j]);sLoc.aHash[iKey];iKey=walNextHash(iKey)){
|
||||
if( sLoc.aHash[iKey]==j ) break;
|
||||
}
|
||||
assert( aHash[iKey]==j );
|
||||
assert( sLoc.aHash[iKey]==j );
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
|
||||
@@ -1030,11 +1031,9 @@ static void walCleanupHash(Wal *pWal){
|
||||
*/
|
||||
static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
|
||||
int rc; /* Return code */
|
||||
u32 iZero = 0; /* One less than frame number of aPgno[1] */
|
||||
volatile u32 *aPgno = 0; /* Page number array */
|
||||
volatile ht_slot *aHash = 0; /* Hash table */
|
||||
WalHashLoc sLoc; /* Wal-index hash table location */
|
||||
|
||||
rc = walHashGet(pWal, walFramePage(iFrame), &aHash, &aPgno, &iZero);
|
||||
rc = walHashGet(pWal, walFramePage(iFrame), &sLoc);
|
||||
|
||||
/* Assuming the wal-index file was successfully mapped, populate the
|
||||
** page number array and hash table entry.
|
||||
@@ -1044,15 +1043,16 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
|
||||
int idx; /* Value to write to hash-table slot */
|
||||
int nCollide; /* Number of hash collisions */
|
||||
|
||||
idx = iFrame - iZero;
|
||||
idx = iFrame - sLoc.iZero;
|
||||
assert( idx <= HASHTABLE_NSLOT/2 + 1 );
|
||||
|
||||
/* If this is the first entry to be added to this hash-table, zero the
|
||||
** entire hash table and aPgno[] array before proceeding.
|
||||
*/
|
||||
if( idx==1 ){
|
||||
int nByte = (int)((u8 *)&aHash[HASHTABLE_NSLOT] - (u8 *)&aPgno[1]);
|
||||
memset((void*)&aPgno[1], 0, nByte);
|
||||
int nByte = (int)((u8 *)&sLoc.aHash[HASHTABLE_NSLOT]
|
||||
- (u8 *)&sLoc.aPgno[1]);
|
||||
memset((void*)&sLoc.aPgno[1], 0, nByte);
|
||||
}
|
||||
|
||||
/* If the entry in aPgno[] is already set, then the previous writer
|
||||
@@ -1061,18 +1061,18 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
|
||||
** Remove the remnants of that writers uncommitted transaction from
|
||||
** the hash-table before writing any new entries.
|
||||
*/
|
||||
if( aPgno[idx] ){
|
||||
if( sLoc.aPgno[idx] ){
|
||||
walCleanupHash(pWal);
|
||||
assert( !aPgno[idx] );
|
||||
assert( !sLoc.aPgno[idx] );
|
||||
}
|
||||
|
||||
/* Write the aPgno[] array entry and the hash-table slot. */
|
||||
nCollide = idx;
|
||||
for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){
|
||||
for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
|
||||
if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
aPgno[idx] = iPage;
|
||||
aHash[iKey] = (ht_slot)idx;
|
||||
sLoc.aPgno[idx] = iPage;
|
||||
sLoc.aHash[iKey] = (ht_slot)idx;
|
||||
|
||||
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
/* Verify that the number of entries in the hash table exactly equals
|
||||
@@ -1081,7 +1081,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
|
||||
{
|
||||
int i; /* Loop counter */
|
||||
int nEntry = 0; /* Number of entries in the hash table */
|
||||
for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; }
|
||||
for(i=0; i<HASHTABLE_NSLOT; i++){ if( sLoc.aHash[i] ) nEntry++; }
|
||||
assert( nEntry==idx );
|
||||
}
|
||||
|
||||
@@ -1093,10 +1093,12 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
|
||||
if( (idx&0x3ff)==0 ){
|
||||
int i; /* Loop counter */
|
||||
for(i=1; i<=idx; i++){
|
||||
for(iKey=walHash(aPgno[i]); aHash[iKey]; iKey=walNextHash(iKey)){
|
||||
if( aHash[iKey]==i ) break;
|
||||
for(iKey=walHash(sLoc.aPgno[i]);
|
||||
sLoc.aHash[iKey];
|
||||
iKey=walNextHash(iKey)){
|
||||
if( sLoc.aHash[iKey]==i ) break;
|
||||
}
|
||||
assert( aHash[iKey]==i );
|
||||
assert( sLoc.aHash[iKey]==i );
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
|
||||
@@ -1634,33 +1636,31 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
|
||||
}
|
||||
|
||||
for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && i<nSegment; i++){
|
||||
volatile ht_slot *aHash;
|
||||
u32 iZero;
|
||||
volatile u32 *aPgno;
|
||||
WalHashLoc sLoc;
|
||||
|
||||
rc = walHashGet(pWal, i, &aHash, &aPgno, &iZero);
|
||||
rc = walHashGet(pWal, i, &sLoc);
|
||||
if( rc==SQLITE_OK ){
|
||||
int j; /* Counter variable */
|
||||
int nEntry; /* Number of entries in this segment */
|
||||
ht_slot *aIndex; /* Sorted index for this segment */
|
||||
|
||||
aPgno++;
|
||||
sLoc.aPgno++;
|
||||
if( (i+1)==nSegment ){
|
||||
nEntry = (int)(iLast - iZero);
|
||||
nEntry = (int)(iLast - sLoc.iZero);
|
||||
}else{
|
||||
nEntry = (int)((u32*)aHash - (u32*)aPgno);
|
||||
nEntry = (int)((u32*)sLoc.aHash - (u32*)sLoc.aPgno);
|
||||
}
|
||||
aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[iZero];
|
||||
iZero++;
|
||||
aIndex = &((ht_slot *)&p->aSegment[p->nSegment])[sLoc.iZero];
|
||||
sLoc.iZero++;
|
||||
|
||||
for(j=0; j<nEntry; j++){
|
||||
aIndex[j] = (ht_slot)j;
|
||||
}
|
||||
walMergesort((u32 *)aPgno, aTmp, aIndex, &nEntry);
|
||||
p->aSegment[i].iZero = iZero;
|
||||
walMergesort((u32 *)sLoc.aPgno, aTmp, aIndex, &nEntry);
|
||||
p->aSegment[i].iZero = sLoc.iZero;
|
||||
p->aSegment[i].nEntry = nEntry;
|
||||
p->aSegment[i].aIndex = aIndex;
|
||||
p->aSegment[i].aPgno = (u32 *)aPgno;
|
||||
p->aSegment[i].aPgno = (u32 *)sLoc.aPgno;
|
||||
}
|
||||
}
|
||||
sqlite3_free(aTmp);
|
||||
@@ -2673,16 +2673,14 @@ int sqlite3WalSnapshotRecover(Wal *pWal){
|
||||
}else{
|
||||
u32 i = pInfo->nBackfillAttempted;
|
||||
for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
|
||||
volatile ht_slot *dummy;
|
||||
volatile u32 *aPgno; /* Array of page numbers */
|
||||
u32 iZero; /* Frame corresponding to aPgno[0] */
|
||||
WalHashLoc sLoc; /* Hash table location */
|
||||
u32 pgno; /* Page number in db file */
|
||||
i64 iDbOff; /* Offset of db file entry */
|
||||
i64 iWalOff; /* Offset of wal file entry */
|
||||
|
||||
rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero);
|
||||
rc = walHashGet(pWal, walFramePage(i), &sLoc);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
pgno = aPgno[i-iZero];
|
||||
pgno = sLoc.aPgno[i-sLoc.iZero];
|
||||
iDbOff = (i64)(pgno-1) * szPage;
|
||||
|
||||
if( iDbOff+szPage<=szDb ){
|
||||
@@ -2883,21 +2881,20 @@ int sqlite3WalFindFrame(
|
||||
*/
|
||||
iMinHash = walFramePage(pWal->minFrame);
|
||||
for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){
|
||||
volatile ht_slot *aHash; /* Pointer to hash table */
|
||||
volatile u32 *aPgno; /* Pointer to array of page numbers */
|
||||
u32 iZero; /* Frame number corresponding to aPgno[0] */
|
||||
WalHashLoc sLoc; /* Hash table location */
|
||||
int iKey; /* Hash slot index */
|
||||
int nCollide; /* Number of hash collisions remaining */
|
||||
int rc; /* Error code */
|
||||
|
||||
rc = walHashGet(pWal, iHash, &aHash, &aPgno, &iZero);
|
||||
rc = walHashGet(pWal, iHash, &sLoc);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
nCollide = HASHTABLE_NSLOT;
|
||||
for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){
|
||||
u32 iFrame = aHash[iKey] + iZero;
|
||||
if( iFrame<=iLast && iFrame>=pWal->minFrame && aPgno[aHash[iKey]]==pgno ){
|
||||
for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
|
||||
u32 iFrame = sLoc.aHash[iKey] + sLoc.iZero;
|
||||
if( iFrame<=iLast && iFrame>=pWal->minFrame
|
||||
&& sLoc.aPgno[sLoc.aHash[iKey]]==pgno ){
|
||||
assert( iFrame>iRead || CORRUPT_DB );
|
||||
iRead = iFrame;
|
||||
}
|
||||
|
Reference in New Issue
Block a user