From: drh Date: Wed, 13 Feb 2019 13:48:48 +0000 (+0000) Subject: Performance optimization in the VDBE, and a fix for a harmless compiler X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Freuse-schema-vdbe-opt;p=thirdparty%2Fsqlite.git Performance optimization in the VDBE, and a fix for a harmless compiler warning. FossilOrigin-Name: e002666ac79c3452a772323c6ecc696104341cd842e77541553ec028f188096b --- diff --git a/manifest b/manifest index 77f938b151..9aa847208d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sOPEN_REUSE_SCHEMA\sconnections\sreloading\sthe\stemp\sschema. -D 2019-02-13T08:40:34.055 +C Performance\soptimization\sin\sthe\sVDBE,\sand\sa\sfix\sfor\sa\sharmless\scompiler\nwarning. +D 2019-02-13T13:48:48.604 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 56456706c4da271309914c756c9c8ea537685f1c79f8785afa72f968d6810482 @@ -521,7 +521,7 @@ F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683 F src/sqliteInt.h 6173e47d1cddb8c9aa5ccfaa0f40b9f62635050d503245e6439b3cd96fb6a53d F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b -F src/status.c 41d9cc5d5f9d2a470dcf0a28432c66e25c15b86e51535283e9aef632adf02ac8 +F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c b17e7c1629311de001887ad5afa4ed9bfddd85be0bbb7e6fdf16352162c98081 F src/test1.c 353b066e7ec761c4c715c1c20b888e0e7a0b0c0eda7f68c110e032d63713cade @@ -586,7 +586,7 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c 82a2e3f691a3b654be872e305dab1f455e565dedf5e6a90c818c1ab307c00432 F src/vacuum.c 7dbed4a756f014f3ce54e6ae3c403ee725e8179cf73fc6dd5c064e5627649f9f -F src/vdbe.c a9a47fee453e93a725469b3c6d9b58425178658ed3ec50709a08408a293773b3 +F src/vdbe.c 5f0e3dc94889a4e68497127d0bca320401797c7107035bc0408e6b5e49d6d733 F src/vdbe.h 323218c4bfd64c719ba85d05fbc87cdd126991cadb39e73ccac7b59f30c3d53e F src/vdbeInt.h a76d5eed62c76bcd8de7afd3147fac1bc40c5a870582664bcd7d071ef437c37f F src/vdbeapi.c 57a2d794a8833f269b878dbc24e955369bdb379af6c4e93ebc5ce1a20fa3daf4 @@ -1808,7 +1808,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8c07b609fccc43795498b942c733896defd8887e4ddd9e0ef48c124dfcf9fd7f -R 765b6e0bdb51edd5b378e5259607a03d -U dan -Z c13672cd797193c9057764ed19647533 +P 7c2ec2d4cfcda9c0aa6d57bd9a12ff98b78e648533d49da27f91d5a37bf1e001 +R 874fe30becc1a5c03c09070b47052542 +T *branch * reuse-schema-vdbe-opt +T *sym-reuse-schema-vdbe-opt * +T -sym-reuse-schema * +U drh +Z 98b88b6e43c9abf2e2da117ac8e7a62c diff --git a/manifest.uuid b/manifest.uuid index c092348ad2..82b709ee6a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7c2ec2d4cfcda9c0aa6d57bd9a12ff98b78e648533d49da27f91d5a37bf1e001 \ No newline at end of file +e002666ac79c3452a772323c6ecc696104341cd842e77541553ec028f188096b \ No newline at end of file diff --git a/src/status.c b/src/status.c index d0dc0b734f..a5a39f4c18 100644 --- a/src/status.c +++ b/src/status.c @@ -282,7 +282,6 @@ int sqlite3_db_status( Schema *pSchema = db->aDb[i].pSchema; if( ALWAYS(pSchema!=0) ){ HashElem *p; - int nStart = nByte; nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * ( pSchema->tblHash.count diff --git a/src/vdbe.c b/src/vdbe.c index 456b6e98d1..2f65d708f0 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -412,6 +412,86 @@ static u16 numericType(Mem *pMem){ return 0; } +/* +** This is the implementation of the OP_ParseSchema opcode. It is factored +** out of the main sqlite3VdbeExec() routine because it is not a performance- +** critical opcode and by factoring it out, it frees up registers in order +** to help the compiler optimizer do a better job with the other opcodes +** that are performance critical. +*/ +static SQLITE_NOINLINE int parseSchemaOp(Vdbe *p, VdbeOp *pOp, sqlite3 *db){ + int iDb; + const char *zMaster; + char *zSql; + InitData initData; + int bRelease; + int rc = SQLITE_OK; + + /* Any prepared statement that invokes this opcode will hold mutexes + ** on every btree. This is a prerequisite for invoking + ** sqlite3InitCallback(). + */ +#ifdef SQLITE_DEBUG + for(iDb=0; iDbnDb; iDb++){ + assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); + } +#endif + + iDb = pOp->p1; + assert( iDb>=0 && iDbnDb ); + assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); + +#ifndef SQLITE_OMIT_ALTERTABLE + if( pOp->p4.z==0 ){ + assert( !IsReuseSchema(db) || iDb==1 ); + sqlite3SchemaClear(db->aDb[iDb].pSchema); + db->mDbFlags &= ~DBFLAG_SchemaKnownOk; + rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable); + db->mDbFlags |= DBFLAG_SchemaChange; + p->expired = 0; + }else +#endif + { + zMaster = MASTER_NAME; + initData.db = db; + initData.iDb = iDb; + initData.pzErrMsg = &p->zErrMsg; + initData.mInitFlags = 0; + zSql = sqlite3MPrintf(db, + "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", + db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); + if( zSql==0 ){ + rc = SQLITE_NOMEM_BKPT; + }else{ + bRelease = sqlite3LockReusableSchema(db); + if( IsReuseSchema(db) ){ + rc = sqlite3Init(db, &p->zErrMsg); + if( rc ){ + sqlite3UnlockReusableSchema(db, bRelease); + return rc; + } + } + assert( db->init.busy==0 ); + db->init.busy = 1; + initData.rc = SQLITE_OK; + initData.nInitRow = 0; + assert( !db->mallocFailed ); + rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); + sqlite3UnlockReusableSchema(db, bRelease); + if( rc==SQLITE_OK ) rc = initData.rc; + if( rc==SQLITE_OK && initData.nInitRow==0 ){ + /* The OP_ParseSchema opcode with a non-NULL P4 argument should parse + ** at least one SQL statement. Any less than that indicates that + ** the sqlite_master table is corrupt. */ + rc = SQLITE_CORRUPT_BKPT; + } + sqlite3DbFreeNN(db, zSql); + db->init.busy = 0; + } + } + return rc; +} + #ifdef SQLITE_DEBUG /* ** Write a nice string representation of the contents of cell pMem @@ -5757,74 +5837,7 @@ case OP_SqlExec: { ** then runs the new virtual machine. It is thus a re-entrant opcode. */ case OP_ParseSchema: { - int iDb; - const char *zMaster; - char *zSql; - InitData initData; - int bRelease; - - /* Any prepared statement that invokes this opcode will hold mutexes - ** on every btree. This is a prerequisite for invoking - ** sqlite3InitCallback(). - */ -#ifdef SQLITE_DEBUG - for(iDb=0; iDbnDb; iDb++){ - assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); - } -#endif - - iDb = pOp->p1; - assert( iDb>=0 && iDbnDb ); - assert( DbHasProperty(db, iDb, DB_SchemaLoaded) ); - -#ifndef SQLITE_OMIT_ALTERTABLE - if( pOp->p4.z==0 ){ - assert( !IsReuseSchema(db) || iDb==1 ); - sqlite3SchemaClear(db->aDb[iDb].pSchema); - db->mDbFlags &= ~DBFLAG_SchemaKnownOk; - rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable); - db->mDbFlags |= DBFLAG_SchemaChange; - p->expired = 0; - }else -#endif - { - zMaster = MASTER_NAME; - initData.db = db; - initData.iDb = iDb; - initData.pzErrMsg = &p->zErrMsg; - initData.mInitFlags = 0; - zSql = sqlite3MPrintf(db, - "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid", - db->aDb[iDb].zDbSName, zMaster, pOp->p4.z); - if( zSql==0 ){ - rc = SQLITE_NOMEM_BKPT; - }else{ - bRelease = sqlite3LockReusableSchema(db); - if( IsReuseSchema(db) ){ - rc = sqlite3Init(db, &p->zErrMsg); - if( rc ){ - sqlite3UnlockReusableSchema(db, bRelease); - goto abort_due_to_error; - } - } - assert( db->init.busy==0 ); - db->init.busy = 1; - initData.rc = SQLITE_OK; - initData.nInitRow = 0; - assert( !db->mallocFailed ); - rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0); - sqlite3UnlockReusableSchema(db, bRelease); - if( rc==SQLITE_OK ) rc = initData.rc; - if( rc==SQLITE_OK && initData.nInitRow==0 ){ - /* The OP_ParseSchema opcode with a non-NULL P4 argument should parse - ** at least one SQL statement. Any less than that indicates that - ** the sqlite_master table is corrupt. */ - rc = SQLITE_CORRUPT_BKPT; - } - sqlite3DbFreeNN(db, zSql); - db->init.busy = 0; - } - } + rc = parseSchemaOp(p, pOp, db); if( rc ){ sqlite3ResetAllSchemasOfConnection(db); if( rc==SQLITE_NOMEM ){