Fix a performance regression: Keep two btree masks in each prepared
statement; one for btrees used and another for btrees that require locks. Only try to lock the btrees identified by the second mask. FossilOrigin-Name: 614de91a504d2231009a9de1305e31fce1b1c5a6
This commit is contained in:
@@ -203,6 +203,14 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true if a particular Btree requires a lock. Return FALSE if
|
||||
** no lock is ever required since it is not sharable.
|
||||
*/
|
||||
int sqlite3BtreeSharable(Btree *p){
|
||||
return p->sharable;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
** Return true if the current thread holds the database connection
|
||||
|
||||
@@ -212,6 +212,7 @@ void sqlite3BtreeCursorList(Btree*);
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
|
||||
int sqlite3BtreeSharable(Btree*);
|
||||
void sqlite3BtreeLeave(Btree*);
|
||||
void sqlite3BtreeEnterCursor(BtCursor*);
|
||||
void sqlite3BtreeLeaveCursor(BtCursor*);
|
||||
@@ -224,6 +225,7 @@ void sqlite3BtreeCursorList(Btree*);
|
||||
#endif
|
||||
#else
|
||||
|
||||
# define sqlite3BtreeSharable(X) 0
|
||||
# define sqlite3BtreeLeave(X)
|
||||
# define sqlite3BtreeEnterCursor(X)
|
||||
# define sqlite3BtreeLeaveCursor(X)
|
||||
|
||||
@@ -4645,8 +4645,6 @@ case OP_ParseSchema: {
|
||||
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
|
||||
}
|
||||
#endif
|
||||
assert( p->btreeMask == ~(yDbMask)0 );
|
||||
|
||||
|
||||
iDb = pOp->p1;
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
|
||||
@@ -303,6 +303,7 @@ struct Vdbe {
|
||||
u8 isPrepareV2; /* True if prepared with prepare_v2() */
|
||||
int nChange; /* Number of db changes made since last reset */
|
||||
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
||||
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
|
||||
int iStatement; /* Statement number (or 0 if has not opened stmt) */
|
||||
int aCounter[3]; /* Counters used by sqlite3_stmt_status() */
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
|
||||
+21
-10
@@ -160,7 +160,8 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
if( op==OP_ParseSchema ){
|
||||
/* Any program that uses the OP_ParseSchema opcode needs to lock
|
||||
** all btrees. */
|
||||
p->btreeMask = ~(yDbMask)0;
|
||||
int j;
|
||||
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
pOp->zComment = 0;
|
||||
@@ -958,6 +959,9 @@ void sqlite3VdbeUsesBtree(Vdbe *p, int i){
|
||||
assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
|
||||
assert( i<(int)sizeof(p->btreeMask)*8 );
|
||||
p->btreeMask |= ((yDbMask)1)<<i;
|
||||
if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
|
||||
p->lockMask |= ((yDbMask)1)<<i;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
||||
@@ -985,11 +989,15 @@ void sqlite3VdbeUsesBtree(Vdbe *p, int i){
|
||||
void sqlite3VdbeEnter(Vdbe *p){
|
||||
int i;
|
||||
yDbMask mask;
|
||||
sqlite3 *db = p->db;
|
||||
Db *aDb = db->aDb;
|
||||
int nDb = db->nDb;
|
||||
sqlite3 *db;
|
||||
Db *aDb;
|
||||
int nDb;
|
||||
if( p->lockMask==0 ) return; /* The common case */
|
||||
db = p->db;
|
||||
aDb = db->aDb;
|
||||
nDb = db->nDb;
|
||||
for(i=0, mask=1; i<nDb; i++, mask += mask){
|
||||
if( i!=1 && (mask & p->btreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
|
||||
if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
|
||||
sqlite3BtreeEnter(aDb[i].pBt);
|
||||
}
|
||||
}
|
||||
@@ -1003,12 +1011,15 @@ void sqlite3VdbeEnter(Vdbe *p){
|
||||
void sqlite3VdbeLeave(Vdbe *p){
|
||||
int i;
|
||||
yDbMask mask;
|
||||
sqlite3 *db = p->db;
|
||||
Db *aDb = db->aDb;
|
||||
int nDb = db->nDb;
|
||||
|
||||
sqlite3 *db;
|
||||
Db *aDb;
|
||||
int nDb;
|
||||
if( p->lockMask==0 ) return; /* The common case */
|
||||
db = p->db;
|
||||
aDb = db->aDb;
|
||||
nDb = db->nDb;
|
||||
for(i=0, mask=1; i<nDb; i++, mask += mask){
|
||||
if( i!=1 && (mask & p->btreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
|
||||
if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
|
||||
sqlite3BtreeLeave(aDb[i].pBt);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user