/ Check-in [17ce1c49]
Login

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

Overview
Comment:Performance optimization to the lookaside-memory disabling mechanism.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 17ce1c49cb0ed6fdd8c7c33431bc2afa217f1092c99b8dd608890a8e7aec7fb1
User & Date: drh 2019-10-05 14:39:36
Context
2019-10-05
15:28
Reorder two comparisons for a small performance gain in OP_Transaction. check-in: d7667f65 user: drh tags: trunk
14:39
Performance optimization to the lookaside-memory disabling mechanism. check-in: 17ce1c49 user: drh tags: trunk
2019-10-04
15:03
Version 3.30.0 check-in: c20a3533 user: drh tags: trunk, release, version-3.30.0
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/analyze.c.

  1850   1850       Index *pIdx = sqliteHashData(i);
  1851   1851       if( !pIdx->hasStat1 ) sqlite3DefaultRowEst(pIdx);
  1852   1852     }
  1853   1853   
  1854   1854     /* Load the statistics from the sqlite_stat4 table. */
  1855   1855   #ifdef SQLITE_ENABLE_STAT4
  1856   1856     if( rc==SQLITE_OK ){
  1857         -    db->lookaside.bDisable++;
         1857  +    DisableLookaside;
  1858   1858       rc = loadStat4(db, sInfo.zDatabase);
  1859         -    db->lookaside.bDisable--;
         1859  +    EnableLookaside;
  1860   1860     }
  1861   1861     for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
  1862   1862       Index *pIdx = sqliteHashData(i);
  1863   1863       sqlite3_free(pIdx->aiRowEst);
  1864   1864       pIdx->aiRowEst = 0;
  1865   1865     }
  1866   1866   #endif

Changes to src/build.c.

  2443   2443   #ifndef SQLITE_OMIT_ALTERTABLE
  2444   2444       u8 eParseMode = pParse->eParseMode;
  2445   2445       pParse->eParseMode = PARSE_MODE_NORMAL;
  2446   2446   #endif
  2447   2447       n = pParse->nTab;
  2448   2448       sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
  2449   2449       pTable->nCol = -1;
  2450         -    db->lookaside.bDisable++;
         2450  +    DisableLookaside;
  2451   2451   #ifndef SQLITE_OMIT_AUTHORIZATION
  2452   2452       xAuth = db->xAuth;
  2453   2453       db->xAuth = 0;
  2454   2454       pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
  2455   2455       db->xAuth = xAuth;
  2456   2456   #else
  2457   2457       pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
................................................................................
  2485   2485         assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
  2486   2486       }else{
  2487   2487         pTable->nCol = 0;
  2488   2488         nErr++;
  2489   2489       }
  2490   2490       sqlite3DeleteTable(db, pSelTab);
  2491   2491       sqlite3SelectDelete(db, pSel);
  2492         -    db->lookaside.bDisable--;
         2492  +    EnableLookaside;
  2493   2493   #ifndef SQLITE_OMIT_ALTERTABLE
  2494   2494       pParse->eParseMode = eParseMode;
  2495   2495   #endif
  2496   2496     } else {
  2497   2497       nErr++;
  2498   2498     }
  2499   2499     pTable->pSchema->schemaFlags |= DB_UnresetViews;

Changes to src/fkey.c.

  1295   1295             pWhere,
  1296   1296             0, 0, 0, 0, 0
  1297   1297         );
  1298   1298         pWhere = 0;
  1299   1299       }
  1300   1300   
  1301   1301       /* Disable lookaside memory allocation */
  1302         -    db->lookaside.bDisable++;
         1302  +    DisableLookaside;
  1303   1303   
  1304   1304       pTrigger = (Trigger *)sqlite3DbMallocZero(db, 
  1305   1305           sizeof(Trigger) +         /* struct Trigger */
  1306   1306           sizeof(TriggerStep) +     /* Single step in trigger program */
  1307   1307           nFrom + 1                 /* Space for pStep->zTarget */
  1308   1308       );
  1309   1309       if( pTrigger ){
................................................................................
  1317   1317         if( pWhen ){
  1318   1318           pWhen = sqlite3PExpr(pParse, TK_NOT, pWhen, 0);
  1319   1319           pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
  1320   1320         }
  1321   1321       }
  1322   1322   
  1323   1323       /* Re-enable the lookaside buffer, if it was disabled earlier. */
  1324         -    db->lookaside.bDisable--;
         1324  +    EnableLookaside;
  1325   1325   
  1326   1326       sqlite3ExprDelete(db, pWhere);
  1327   1327       sqlite3ExprDelete(db, pWhen);
  1328   1328       sqlite3ExprListDelete(db, pList);
  1329   1329       sqlite3SelectDelete(db, pSelect);
  1330   1330       if( db->mallocFailed==1 ){
  1331   1331         fkTriggerDelete(db, pTrigger);

Changes to src/main.c.

   711    711     }else{
   712    712       pStart = pBuf;
   713    713     }
   714    714     db->lookaside.pStart = pStart;
   715    715     db->lookaside.pInit = 0;
   716    716     db->lookaside.pFree = 0;
   717    717     db->lookaside.sz = (u16)sz;
          718  +  db->lookaside.szTrue = (u16)sz;
   718    719     if( pStart ){
   719    720       int i;
   720    721       LookasideSlot *p;
   721    722       assert( sz > (int)sizeof(LookasideSlot*) );
   722    723       db->lookaside.nSlot = cnt;
   723    724       p = (LookasideSlot*)pStart;
   724    725       for(i=cnt-1; i>=0; i--){
................................................................................
   729    730       db->lookaside.pEnd = p;
   730    731       db->lookaside.bDisable = 0;
   731    732       db->lookaside.bMalloced = pBuf==0 ?1:0;
   732    733     }else{
   733    734       db->lookaside.pStart = db;
   734    735       db->lookaside.pEnd = db;
   735    736       db->lookaside.bDisable = 1;
          737  +    db->lookaside.sz = 0;
   736    738       db->lookaside.bMalloced = 0;
   737    739       db->lookaside.nSlot = 0;
   738    740     }
   739    741   #endif /* SQLITE_OMIT_LOOKASIDE */
   740    742     return SQLITE_OK;
   741    743   }
   742    744   
................................................................................
  3060   3062     }
  3061   3063     sqlite3_mutex_enter(db->mutex);
  3062   3064     db->errMask = 0xff;
  3063   3065     db->nDb = 2;
  3064   3066     db->magic = SQLITE_MAGIC_BUSY;
  3065   3067     db->aDb = db->aDbStatic;
  3066   3068     db->lookaside.bDisable = 1;
         3069  +  db->lookaside.sz = 0;
  3067   3070   
  3068   3071     assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  3069   3072     memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  3070   3073     db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS;
  3071   3074     db->autoCommit = 1;
  3072   3075     db->nextAutovac = -1;
  3073   3076     db->szMmap = sqlite3GlobalConfig.szMmap;

Changes to src/malloc.c.

   294    294         assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
   295    295         assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
   296    296       }
   297    297   #endif
   298    298       return sqlite3GlobalConfig.m.xSize(p);
   299    299     }else{
   300    300       assert( sqlite3_mutex_held(db->mutex) );
   301         -    return db->lookaside.sz;
          301  +    return db->lookaside.szTrue;
   302    302     }
   303    303   }
   304    304   sqlite3_uint64 sqlite3_msize(void *p){
   305    305     assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
   306    306     assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
   307    307     return p ? sqlite3GlobalConfig.m.xSize(p) : 0;
   308    308   }
................................................................................
   346    346         measureAllocationSize(db, p);
   347    347         return;
   348    348       }
   349    349       if( isLookaside(db, p) ){
   350    350         LookasideSlot *pBuf = (LookasideSlot*)p;
   351    351   #ifdef SQLITE_DEBUG
   352    352         /* Trash all content in the buffer being freed */
   353         -      memset(p, 0xaa, db->lookaside.sz);
          353  +      memset(p, 0xaa, db->lookaside.szTrue);
   354    354   #endif
   355    355         pBuf->pNext = db->lookaside.pFree;
   356    356         db->lookaside.pFree = pBuf;
   357    357         return;
   358    358       }
   359    359     }
   360    360     assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
................................................................................
   506    506   }
   507    507   void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
   508    508   #ifndef SQLITE_OMIT_LOOKASIDE
   509    509     LookasideSlot *pBuf;
   510    510     assert( db!=0 );
   511    511     assert( sqlite3_mutex_held(db->mutex) );
   512    512     assert( db->pnBytesFreed==0 );
   513         -  if( db->lookaside.bDisable==0 ){
   514         -    assert( db->mallocFailed==0 );
   515         -    if( n>db->lookaside.sz ){
   516         -      db->lookaside.anStat[1]++;
   517         -    }else if( (pBuf = db->lookaside.pFree)!=0 ){
   518         -      db->lookaside.pFree = pBuf->pNext;
   519         -      db->lookaside.anStat[0]++;
   520         -      return (void*)pBuf;
   521         -    }else if( (pBuf = db->lookaside.pInit)!=0 ){
   522         -      db->lookaside.pInit = pBuf->pNext;
   523         -      db->lookaside.anStat[0]++;
   524         -      return (void*)pBuf;
   525         -    }else{
   526         -      db->lookaside.anStat[2]++;
          513  +  if( n>db->lookaside.sz ){
          514  +    if( db->lookaside.bDisable ){
          515  +      return db->mallocFailed ? 0 : dbMallocRawFinish(db, n);
   527    516       }
   528         -  }else if( db->mallocFailed ){
   529         -    return 0;
          517  +    db->lookaside.anStat[1]++;
          518  +  }else if( (pBuf = db->lookaside.pFree)!=0 ){
          519  +    db->lookaside.pFree = pBuf->pNext;
          520  +    db->lookaside.anStat[0]++;
          521  +    return (void*)pBuf;
          522  +  }else if( (pBuf = db->lookaside.pInit)!=0 ){
          523  +    db->lookaside.pInit = pBuf->pNext;
          524  +    db->lookaside.anStat[0]++;
          525  +    return (void*)pBuf;
          526  +  }else{
          527  +    db->lookaside.anStat[2]++;
   530    528     }
   531    529   #else
   532    530     assert( db!=0 );
   533    531     assert( sqlite3_mutex_held(db->mutex) );
   534    532     assert( db->pnBytesFreed==0 );
   535    533     if( db->mallocFailed ){
   536    534       return 0;
................................................................................
   546    544   ** Resize the block of memory pointed to by p to n bytes. If the
   547    545   ** resize fails, set the mallocFailed flag in the connection object.
   548    546   */
   549    547   void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
   550    548     assert( db!=0 );
   551    549     if( p==0 ) return sqlite3DbMallocRawNN(db, n);
   552    550     assert( sqlite3_mutex_held(db->mutex) );
   553         -  if( isLookaside(db,p) && n<=db->lookaside.sz ) return p;
          551  +  if( isLookaside(db,p) && n<=db->lookaside.szTrue ) return p;
   554    552     return dbReallocFinish(db, p, n);
   555    553   }
   556    554   static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
   557    555     void *pNew = 0;
   558    556     assert( db!=0 );
   559    557     assert( p!=0 );
   560    558     if( db->mallocFailed==0 ){
   561    559       if( isLookaside(db, p) ){
   562    560         pNew = sqlite3DbMallocRawNN(db, n);
   563    561         if( pNew ){
   564         -        memcpy(pNew, p, db->lookaside.sz);
          562  +        memcpy(pNew, p, db->lookaside.szTrue);
   565    563           sqlite3DbFree(db, p);
   566    564         }
   567    565       }else{
   568    566         assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
   569    567         assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
   570    568         sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
   571    569         pNew = sqlite3_realloc64(p, n);
................................................................................
   656    654   */
   657    655   void sqlite3OomFault(sqlite3 *db){
   658    656     if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
   659    657       db->mallocFailed = 1;
   660    658       if( db->nVdbeExec>0 ){
   661    659         db->u1.isInterrupted = 1;
   662    660       }
   663         -    db->lookaside.bDisable++;
          661  +    DisableLookaside;
   664    662       if( db->pParse ){
   665    663         db->pParse->rc = SQLITE_NOMEM_BKPT;
   666    664       }
   667    665     }
   668    666   }
   669    667   
   670    668   /*
................................................................................
   675    673   ** VDBEs.
   676    674   */
   677    675   void sqlite3OomClear(sqlite3 *db){
   678    676     if( db->mallocFailed && db->nVdbeExec==0 ){
   679    677       db->mallocFailed = 0;
   680    678       db->u1.isInterrupted = 0;
   681    679       assert( db->lookaside.bDisable>0 );
   682         -    db->lookaside.bDisable--;
          680  +    EnableLookaside;
   683    681     }
   684    682   }
   685    683   
   686    684   /*
   687    685   ** Take actions at the end of an API call to indicate an OOM error
   688    686   */
   689    687   static SQLITE_NOINLINE int apiOomError(sqlite3 *db){

Changes to src/parse.y.

   102    102   struct FrameBound     { int eType; Expr *pExpr; };
   103    103   
   104    104   /*
   105    105   ** Disable lookaside memory allocation for objects that might be
   106    106   ** shared across database connections.
   107    107   */
   108    108   static void disableLookaside(Parse *pParse){
          109  +  sqlite3 *db = pParse->db;
   109    110     pParse->disableLookaside++;
   110         -  pParse->db->lookaside.bDisable++;
          111  +  DisableLookaside;
   111    112   }
   112    113   
   113    114   } // end %include
   114    115   
   115    116   // Input is a single SQL command
   116    117   input ::= cmdlist.
   117    118   cmdlist ::= cmdlist ecmd.

Changes to src/prepare.c.

   523    523   void sqlite3ParserReset(Parse *pParse){
   524    524     sqlite3 *db = pParse->db;
   525    525     sqlite3DbFree(db, pParse->aLabel);
   526    526     sqlite3ExprListDelete(db, pParse->pConstExpr);
   527    527     if( db ){
   528    528       assert( db->lookaside.bDisable >= pParse->disableLookaside );
   529    529       db->lookaside.bDisable -= pParse->disableLookaside;
          530  +    db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
   530    531     }
   531    532     pParse->disableLookaside = 0;
   532    533   }
   533    534   
   534    535   /*
   535    536   ** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
   536    537   */
................................................................................
   556    557     assert( sqlite3_mutex_held(db->mutex) );
   557    558   
   558    559     /* For a long-term use prepared statement avoid the use of
   559    560     ** lookaside memory.
   560    561     */
   561    562     if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
   562    563       sParse.disableLookaside++;
   563         -    db->lookaside.bDisable++;
          564  +    DisableLookaside;
   564    565     }
   565    566     sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0;
   566    567   
   567    568     /* Check to verify that it is possible to get a read lock on all
   568    569     ** database schemas.  The inability to get a read lock indicates that
   569    570     ** some other database connection is holding a write-lock, which in
   570    571     ** turn means that the other connection has made uncommitted changes

Changes to src/sqliteInt.h.

  1267   1267   **
  1268   1268   ** Lookaside allocations are only allowed for objects that are associated
  1269   1269   ** with a particular database connection.  Hence, schema information cannot
  1270   1270   ** be stored in lookaside because in shared cache mode the schema information
  1271   1271   ** is shared by multiple database connections.  Therefore, while parsing
  1272   1272   ** schema information, the Lookaside.bEnabled flag is cleared so that
  1273   1273   ** lookaside allocations are not used to construct the schema objects.
         1274  +**
         1275  +** New lookaside allocations are only allowed if bDisable==0.  When
         1276  +** bDisable is greater than zero, sz is set to zero which effectively
         1277  +** disables lookaside without adding a new test for the bDisable flag
         1278  +** in a performance-critical path.  sz should be set by to szTrue whenever
         1279  +** bDisable changes back to zero.
  1274   1280   */
  1275   1281   struct Lookaside {
  1276   1282     u32 bDisable;           /* Only operate the lookaside when zero */
  1277   1283     u16 sz;                 /* Size of each buffer in bytes */
         1284  +  u16 szTrue;             /* True value of sz, even if disabled */
  1278   1285     u8 bMalloced;           /* True if pStart obtained from sqlite3_malloc() */
  1279   1286     u32 nSlot;              /* Number of lookaside slots allocated */
  1280   1287     u32 anStat[3];          /* 0: hits.  1: size misses.  2: full misses */
  1281   1288     LookasideSlot *pInit;   /* List of buffers not previously used */
  1282   1289     LookasideSlot *pFree;   /* List of available buffers */
  1283   1290     void *pStart;           /* First byte of available memory space */
  1284   1291     void *pEnd;             /* First byte past end of available space */
  1285   1292   };
  1286   1293   struct LookasideSlot {
  1287   1294     LookasideSlot *pNext;    /* Next buffer in the list of free buffers */
  1288   1295   };
         1296  +
         1297  +#define DisableLookaside  db->lookaside.bDisable++;db->lookaside.sz=0
         1298  +#define EnableLookaside   db->lookaside.bDisable--;\
         1299  +   db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue
  1289   1300   
  1290   1301   /*
  1291   1302   ** A hash table for built-in function definitions.  (Application-defined
  1292   1303   ** functions use a regular table table from hash.h.)
  1293   1304   **
  1294   1305   ** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
  1295   1306   ** Collisions are on the FuncDef.u.pHash chain.  Use the SQLITE_FUNC_HASH()