/ Check-in [3f58e7c8]
Login

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

Overview
Comment:Add the sqlite3_db_release_memory() interface and the shrink_memory pragma.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3f58e7c8895d1252eff56282c08b1a6f1194452c
User & Date: drh 2011-11-16 19:29:17
Context
2011-11-16
23:29
Back out the [ceee03c79a] change. check-in: 69ec53fc user: drh tags: trunk
19:29
Add the sqlite3_db_release_memory() interface and the shrink_memory pragma. check-in: 3f58e7c8 user: drh tags: trunk
18:08
Merge the PCACHE2 changes into trunk. check-in: 457513f2 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/main.c.

   525    525   
   526    526   /*
   527    527   ** Return the mutex associated with a database connection.
   528    528   */
   529    529   sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){
   530    530     return db->mutex;
   531    531   }
          532  +
          533  +/*
          534  +** Free up as much memory as we can from the given database
          535  +** connection.
          536  +*/
          537  +int sqlite3_db_release_memory(sqlite3 *db){
          538  +  int i;
          539  +  sqlite3BtreeEnterAll(db);
          540  +  for(i=0; i<db->nDb; i++){
          541  +    Btree *pBt = db->aDb[i].pBt;
          542  +    if( pBt ){
          543  +      Pager *pPager = sqlite3BtreePager(pBt);
          544  +      sqlite3PagerShrink(pPager);
          545  +    }
          546  +  }
          547  +  sqlite3BtreeLeaveAll(db);
          548  +  return SQLITE_OK;
          549  +}
   532    550   
   533    551   /*
   534    552   ** Configuration settings for an individual database connection
   535    553   */
   536    554   int sqlite3_db_config(sqlite3 *db, int op, ...){
   537    555     va_list ap;
   538    556     int rc;

Changes to src/pager.c.

  3289   3289   
  3290   3290   /*
  3291   3291   ** Change the maximum number of in-memory pages that are allowed.
  3292   3292   */
  3293   3293   void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
  3294   3294     sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
  3295   3295   }
         3296  +
         3297  +/*
         3298  +** Free as much memory as possible from the pager.
         3299  +*/
         3300  +void sqlite3PagerShrink(Pager *pPager){
         3301  +  sqlite3PcacheShrink(pPager->pPCache);
         3302  +}
  3296   3303   
  3297   3304   /*
  3298   3305   ** Adjust the robustness of the database to damage due to OS crashes
  3299   3306   ** or power failures by changing the number of syncs()s when writing
  3300   3307   ** the rollback journal.  There are three levels:
  3301   3308   **
  3302   3309   **    OFF       sqlite3OsSync() is never called.  This is the default

Changes to src/pager.h.

    99     99   int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
   100    100   
   101    101   /* Functions used to configure a Pager object. */
   102    102   void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
   103    103   int sqlite3PagerSetPagesize(Pager*, u32*, int);
   104    104   int sqlite3PagerMaxPageCount(Pager*, int);
   105    105   void sqlite3PagerSetCachesize(Pager*, int);
          106  +void sqlite3PagerShrink(Pager*);
   106    107   void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
   107    108   int sqlite3PagerLockingMode(Pager *, int);
   108    109   int sqlite3PagerSetJournalMode(Pager *, int);
   109    110   int sqlite3PagerGetJournalMode(Pager*);
   110    111   int sqlite3PagerOkToChangeJournalMode(Pager*);
   111    112   i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
   112    113   sqlite3_backup **sqlite3PagerBackupPtr(Pager*);

Changes to src/pcache.c.

   590    590   void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
   591    591     pCache->szCache = mxPage;
   592    592     if( pCache->pCache ){
   593    593       sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
   594    594                                              numberOfCachePages(pCache));
   595    595     }
   596    596   }
          597  +
          598  +/*
          599  +** Free up as much memory as possible from the page cache.
          600  +*/
          601  +void sqlite3PcacheShrink(PCache *pCache){
          602  +  if( pCache->pCache ){
          603  +    sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
          604  +  }
          605  +}
   597    606   
   598    607   #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
   599    608   /*
   600    609   ** For all dirty pages currently in the cache, invoke the specified
   601    610   ** callback. This is only used if the SQLITE_CHECK_PAGES macro is
   602    611   ** defined.
   603    612   */

Changes to src/pcache.h.

   137    137   ** the total number of pages cached by purgeable pager-caches to the sum
   138    138   ** of the suggested cache-sizes.
   139    139   */
   140    140   void sqlite3PcacheSetCachesize(PCache *, int);
   141    141   #ifdef SQLITE_TEST
   142    142   int sqlite3PcacheGetCachesize(PCache *);
   143    143   #endif
          144  +
          145  +/* Free up as much memory as possible from the page cache */
          146  +void sqlite3PcacheShrink(PCache*);
   144    147   
   145    148   #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   146    149   /* Try to return memory used by the pcache module to the main memory heap */
   147    150   int sqlite3PcacheReleaseMemory(int);
   148    151   #endif
   149    152   
   150    153   #ifdef SQLITE_TEST
   151    154   void sqlite3PcacheStats(int*,int*,int*,int*);
   152    155   #endif
   153    156   
   154    157   void sqlite3PCacheSetDefault(void);
   155    158   
   156    159   #endif /* _PCACHE_H_ */

Changes to src/pcache1.c.

   223    223     }
   224    224     return p;
   225    225   }
   226    226   
   227    227   /*
   228    228   ** Free an allocated buffer obtained from pcache1Alloc().
   229    229   */
   230         -static void pcache1Free(void *p){
   231         -  if( p==0 ) return;
          230  +static int pcache1Free(void *p){
          231  +  int nFreed = 0;
          232  +  if( p==0 ) return 0;
   232    233     if( p>=pcache1.pStart && p<pcache1.pEnd ){
   233    234       PgFreeslot *pSlot;
   234    235       sqlite3_mutex_enter(pcache1.mutex);
   235    236       sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
   236    237       pSlot = (PgFreeslot*)p;
   237    238       pSlot->pNext = pcache1.pFree;
   238    239       pcache1.pFree = pSlot;
   239    240       pcache1.nFreeSlot++;
   240    241       pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
   241    242       assert( pcache1.nFreeSlot<=pcache1.nSlot );
   242    243       sqlite3_mutex_leave(pcache1.mutex);
   243    244     }else{
   244         -    int iSize;
   245    245       assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
   246    246       sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
   247         -    iSize = sqlite3MallocSize(p);
          247  +    nFreed = sqlite3MallocSize(p);
   248    248       sqlite3_mutex_enter(pcache1.mutex);
   249         -    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
          249  +    sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
   250    250       sqlite3_mutex_leave(pcache1.mutex);
   251    251       sqlite3_free(p);
   252    252     }
          253  +  return nFreed;
   253    254   }
   254    255   
   255    256   #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   256    257   /*
   257    258   ** Return the size of a pcache allocation
   258    259   */
   259    260   static int pcache1MemSize(void *p){
................................................................................
   618    619       pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
   619    620       pCache->nMax = nMax;
   620    621       pCache->n90pct = pCache->nMax*9/10;
   621    622       pcache1EnforceMaxPage(pGroup);
   622    623       pcache1LeaveMutex(pGroup);
   623    624     }
   624    625   }
          626  +
          627  +/*
          628  +** Implementation of the sqlite3_pcache.xShrink method. 
          629  +**
          630  +** Free up as much memory as possible.
          631  +*/
          632  +static void pcache1Shrink(sqlite3_pcache *p){
          633  +  PCache1 *pCache = (PCache1*)p;
          634  +  if( pCache->bPurgeable ){
          635  +    PGroup *pGroup = pCache->pGroup;
          636  +    int savedMaxPage;
          637  +    pcache1EnterMutex(pGroup);
          638  +    savedMaxPage = pGroup->nMaxPage;
          639  +    pGroup->nMaxPage = 0;
          640  +    pcache1EnforceMaxPage(pGroup);
          641  +    pGroup->nMaxPage = savedMaxPage;
          642  +    pcache1LeaveMutex(pGroup);
          643  +  }
          644  +}
   625    645   
   626    646   /*
   627    647   ** Implementation of the sqlite3_pcache.xPagecount method. 
   628    648   */
   629    649   static int pcache1Pagecount(sqlite3_pcache *p){
   630    650     int n;
   631    651     PCache1 *pCache = (PCache1*)p;
................................................................................
   931    951       pcache1Create,           /* xCreate */
   932    952       pcache1Cachesize,        /* xCachesize */
   933    953       pcache1Pagecount,        /* xPagecount */
   934    954       pcache1Fetch,            /* xFetch */
   935    955       pcache1Unpin,            /* xUnpin */
   936    956       pcache1Rekey,            /* xRekey */
   937    957       pcache1Truncate,         /* xTruncate */
   938         -    pcache1Destroy           /* xDestroy */
          958  +    pcache1Destroy,          /* xDestroy */
          959  +    pcache1Shrink            /* xShrink */
   939    960     };
   940    961     sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
   941    962   }
   942    963   
   943    964   #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
   944    965   /*
   945    966   ** This function is called to free superfluous dynamically allocated memory

Changes to src/pragma.c.

  1434   1434       }
  1435   1435       returnSingleInt(pParse, "wal_autocheckpoint", 
  1436   1436          db->xWalCallback==sqlite3WalDefaultHook ? 
  1437   1437              SQLITE_PTR_TO_INT(db->pWalArg) : 0);
  1438   1438     }else
  1439   1439   #endif
  1440   1440   
         1441  +  /*
         1442  +  **  PRAGMA shrink_memory
         1443  +  **
         1444  +  ** This pragma attempts to free as much memory as possible from the
         1445  +  ** current database connection.
         1446  +  */
         1447  +  if( sqlite3StrICmp(zLeft, "shrink_memory")==0 ){
         1448  +    sqlite3_db_release_memory(db);
         1449  +  }else
         1450  +
  1441   1451   #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
  1442   1452     /*
  1443   1453     ** Report the current state of file logs for all databases
  1444   1454     */
  1445   1455     if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
  1446   1456       static const char *const azLockName[] = {
  1447   1457         "unlocked", "shared", "reserved", "pending", "exclusive"

Changes to src/sqlite.h.in.

  4525   4525   ** of heap memory by deallocating non-essential memory allocations
  4526   4526   ** held by the database library.   Memory used to cache database
  4527   4527   ** pages to improve performance is an example of non-essential memory.
  4528   4528   ** ^sqlite3_release_memory() returns the number of bytes actually freed,
  4529   4529   ** which might be more or less than the amount requested.
  4530   4530   ** ^The sqlite3_release_memory() routine is a no-op returning zero
  4531   4531   ** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT].
         4532  +**
         4533  +** See also: [sqlite3_db_release_memory()]
  4532   4534   */
  4533   4535   int sqlite3_release_memory(int);
  4534   4536   
         4537  +/*
         4538  +** CAPI3REF: Free Memory Used By A Database Connection
         4539  +**
         4540  +** ^The sqlite3_db_shrink(D) interface attempts to free as much heap
         4541  +** memory as possible from database connection D. Unlike the
         4542  +** [sqlite3_release_memory()] interface, this interface is effect even
         4543  +** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
         4544  +** omitted.
         4545  +**
         4546  +** See also: [sqlite3_release_memory()]
         4547  +*/
         4548  +int sqlite3_db_release_memory(sqlite3*);
         4549  +
  4535   4550   /*
  4536   4551   ** CAPI3REF: Impose A Limit On Heap Size
  4537   4552   **
  4538   4553   ** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
  4539   4554   ** soft limit on the amount of heap memory that may be allocated by SQLite.
  4540   4555   ** ^SQLite strives to keep heap memory utilization below the soft heap
  4541   4556   ** limit by reducing the number of pages held in the page cache
................................................................................
  6102   6117   **
  6103   6118   ** [[the xDestroy() page cache method]]
  6104   6119   ** ^The xDestroy() method is used to delete a cache allocated by xCreate().
  6105   6120   ** All resources associated with the specified cache should be freed. ^After
  6106   6121   ** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
  6107   6122   ** handle invalid, and will not use it with any other sqlite3_pcache_methods
  6108   6123   ** functions.
         6124  +**
         6125  +** [[the xShrink() page cache method]]
         6126  +** ^SQLite invokes the xShrink() method when it wants the page cache to
         6127  +** free up as much of heap memory as possible.  The page cache implementation
         6128  +** is not obligated to free any memory, but well-behaved implementions should
         6129  +** do their best.
  6109   6130   */
  6110   6131   typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
  6111   6132   struct sqlite3_pcache_methods2 {
  6112   6133     int iVersion;
  6113   6134     void *pArg;
  6114   6135     int (*xInit)(void*);
  6115   6136     void (*xShutdown)(void*);
................................................................................
  6118   6139     int (*xPagecount)(sqlite3_pcache*);
  6119   6140     sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
  6120   6141     void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
  6121   6142     void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, 
  6122   6143         unsigned oldKey, unsigned newKey);
  6123   6144     void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
  6124   6145     void (*xDestroy)(sqlite3_pcache*);
         6146  +  void (*xShrink)(sqlite3_pcache*);
  6125   6147   };
  6126   6148   
  6127   6149   /*
  6128   6150   ** This is the obsolete pcache_methods object that has now been replaced
  6129   6151   ** by sqlite3_pcache_methods2.  This object is not used by SQLite.  It is
  6130   6152   ** retained in the header file for backwards compatibility only.
  6131   6153   */

Changes to src/test1.c.

  4589   4589     }
  4590   4590     amt = sqlite3_release_memory(N);
  4591   4591     Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
  4592   4592   #endif
  4593   4593     return TCL_OK;
  4594   4594   }
  4595   4595   
         4596  +
         4597  +/*
         4598  +** Usage:  sqlite3_db_release_memory DB
         4599  +**
         4600  +** Attempt to release memory currently held by database DB.  Return the
         4601  +** result code (which in the current implementation is always zero).
         4602  +*/
         4603  +static int test_db_release_memory(
         4604  +  void * clientData,
         4605  +  Tcl_Interp *interp,
         4606  +  int objc,
         4607  +  Tcl_Obj *CONST objv[]
         4608  +){
         4609  +  sqlite3 *db;
         4610  +  int rc;
         4611  +  if( objc!=2 ){
         4612  +    Tcl_WrongNumArgs(interp, 1, objv, "DB");
         4613  +    return TCL_ERROR;
         4614  +  }
         4615  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
         4616  +  rc = sqlite3_db_release_memory(db);
         4617  +  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
         4618  +  return TCL_OK;
         4619  +}
         4620  +
  4596   4621   /*
  4597   4622   ** Usage:  sqlite3_soft_heap_limit ?N?
  4598   4623   **
  4599   4624   ** Query or set the soft heap limit for the current thread.  The
  4600   4625   ** limit is only changed if the N is present.  The previous limit
  4601   4626   ** is returned.
  4602   4627   */
................................................................................
  5911   5936        { "sqlite3_step",                  test_step          ,0 },
  5912   5937        { "sqlite3_sql",                   test_sql           ,0 },
  5913   5938        { "sqlite3_next_stmt",             test_next_stmt     ,0 },
  5914   5939        { "sqlite3_stmt_readonly",         test_stmt_readonly ,0 },
  5915   5940        { "uses_stmt_journal",             uses_stmt_journal ,0 },
  5916   5941   
  5917   5942        { "sqlite3_release_memory",        test_release_memory,     0},
         5943  +     { "sqlite3_db_release_memory",     test_db_release_memory,  0},
  5918   5944        { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0},
  5919   5945        { "sqlite3_thread_cleanup",        test_thread_cleanup,     0},
  5920   5946        { "sqlite3_pager_refcounts",       test_pager_refcounts,    0},
  5921   5947   
  5922   5948        { "sqlite3_load_extension",        test_load_extension,     0},
  5923   5949        { "sqlite3_enable_load_extension", test_enable_load,        0},
  5924   5950        { "sqlite3_extended_result_codes", test_extended_result_codes, 0},

Added test/shrink.test.

            1  +# 2011 November 16
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# This file contains test cases for sqlite3_db_release_memory and
           13  +# the PRAGMA shrink_memory statement.
           14  +#
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +
           19  +unset -nocomplain baseline
           20  +do_test shrink-1.1 {
           21  +  db eval {
           22  +    CREATE TABLE t1(x,y);
           23  +    INSERT INTO t1 VALUES(randomblob(1000000),1);
           24  +  }
           25  +  set ::baseline sqlite3_memory_used
           26  +  sqlite3_db_release_memory db
           27  +  expr {$::baseline > [sqlite3_memory_used]+500000}
           28  +} {1}
           29  +do_test shrink-1.2 {
           30  +  set baseline [sqlite3_memory_used]
           31  +  db eval {
           32  +    UPDATE t1 SET y=y+1;
           33  +  }
           34  +  expr {$::baseline+500000 < [sqlite3_memory_used]}
           35  +} {1}
           36  +do_test shrink-1.3 {
           37  +  set baseline [sqlite3_memory_used]
           38  +  db eval {PRAGMA shrink_memory}
           39  +  expr {$::baseline > [sqlite3_memory_used]+500000}
           40  +} {1}
           41  +
           42  +finish_test