1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-04 04:42:17 +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:
drh
2018-06-09 16:49:00 +00:00
parent a46ba6cca5
commit 4ece2f2657
3 changed files with 77 additions and 80 deletions

View File

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

View File

@@ -1 +1 @@
31e480f68dfd887cfd9114f9f9fec53d751d3ecc27e36f55c0166b51b2fbb08c
538a365b7a32ab7fa84f59d7556242cfb59b76d287b6417eb3a823197a354e8e

143
src/wal.c
View File

@@ -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;
}