]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Added support for scratch-memory lookaside allocations. Largely untested.
authordrh <drh@noemail.net>
Wed, 18 Jun 2008 18:12:04 +0000 (18:12 +0000)
committerdrh <drh@noemail.net>
Wed, 18 Jun 2008 18:12:04 +0000 (18:12 +0000)
Added calls to sqlite3_initialize() within malloc APIs. (CVS 5237)

FossilOrigin-Name: 383a78601c70cd832c171344857038e345b9ae5c

manifest
manifest.uuid
src/malloc.c
src/sqlite.h.in
src/test_malloc.c

index d1cd967cbc88d9b9fe3e476d2fb0341f56fcef26..54ef6d54ecfbb16c6054e8ce2d7aff99c396d288 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sa\scall\sto\ssqlite3_initialize()\sto\ssqlite3_mutex_alloc()\s(CVS\s5236)
-D 2008-06-18T18:08:39
+C Added\ssupport\sfor\sscratch-memory\slookaside\sallocations.\s\sLargely\suntested.\nAdded\scalls\sto\ssqlite3_initialize()\swithin\smalloc\sAPIs.\s(CVS\s5237)
+D 2008-06-18T18:12:04
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in dc5608df93faf4406cfd7a1c8ed9ab93d8bfbfd5
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -116,7 +116,7 @@ F src/journal.c cffd2cd214e58c0e99c3ff632b3bee6c7cbb260e
 F src/legacy.c 3626c71fb70912abec9a4312beba753a9ce800df
 F src/loadext.c 2ac671f42a8ce15e2a58155b9d7f6c61eb7e127e
 F src/main.c 619caedf25329b55fe138e581497ec5052bb7e34
-F src/malloc.c 6f84f295db49a79c1e2fc07a63311f5685d47274
+F src/malloc.c 56e48f8147e04f8f8a19fed8e09be351bdf1a48e
 F src/md5.c 008216bbb5d34c6fbab5357aa68575ad8a31516a
 F src/mem1.c 159f10e280f2d9aea597cf938851e61652dd5c3d
 F src/mem2.c 468a7fd5e0ce1909cfb554d7589af1d4a61f14bb
@@ -143,7 +143,7 @@ F src/printf.c 8b063da9dcde26b7c500a01444b718d86f21bc6e
 F src/random.c 362b62e26db90ec9296903377a9d74b4669aa515
 F src/select.c 669687459e7d0193c89de06c5dbed55b4a41191c
 F src/shell.c a12ea645271b7876c8f080146f48e20b00d367ec
-F src/sqlite.h.in 48a3a643fa711141cb53b1c714be74098770e224
+F src/sqlite.h.in 44a3ab74e6677490133ea5efd4ee649dedcf9048
 F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
 F src/sqliteInt.h 24fe828d52f497d4c026ea3b5f6a01d97ea01a2d
 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
@@ -166,7 +166,7 @@ F src/test_devsym.c 6012cb8e3acf812513511025a4fa5d626e0ba19b
 F src/test_func.c f4aafa10f17d52c43a64b47717265802e6e552b3
 F src/test_hexio.c 2f1122aa3f012fa0142ee3c36ce5c902a70cd12f
 F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
-F src/test_malloc.c 5c2c698355613d321f216ece25901be1040cc1fb
+F src/test_malloc.c d44d9ee715ad97503c87d287a802b22421a4c32b
 F src/test_md5.c 28209a4e2068711b5443c33104fe41f21d160071
 F src/test_mutex.c 08640d7547bfadb6997a22d72e63914feaf4bc4f
 F src/test_onefile.c 1f87d4a21cbfb24a7c35e4333fa0bd34d641f68d
@@ -597,7 +597,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P d1a87c3bcc9a32918f1cf743f85cd1a71557220e
-R 2889563ab68a678e373207022a120810
-U danielk1977
-Z 2c927c6baa472eb569be9409a45d4432
+P 8b23b719440aca9fca7e8f409729c3318ff3f80c
+R 34015a602dbdf60ee79902fc40c411d2
+U drh
+Z c0727b87467452e392e22abba32628ae
index f0b6a48c6e21923572bf9f071158f06ae52cc0e1..4bb6c785d6881af3e69ee0fde753d77f1c174045 100644 (file)
@@ -1 +1 @@
-8b23b719440aca9fca7e8f409729c3318ff3f80c
\ No newline at end of file
+383a78601c70cd832c171344857038e345b9ae5c
\ No newline at end of file
index cdfd6a9eae225a45df47e0f09a90324e50fca141..a278e4816610743dd576d866a4891b552ebde45b 100644 (file)
@@ -12,7 +12,7 @@
 **
 ** Memory allocation functions used throughout sqlite.
 **
-** $Id: malloc.c,v 1.19 2008/06/18 17:09:10 danielk1977 Exp $
+** $Id: malloc.c,v 1.20 2008/06/18 18:12:04 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -43,6 +43,7 @@ void sqlite3_soft_heap_limit(int n){
   }else{
     iLimit = n;
   }
+  sqlite3_initialize();
   if( iLimit>0 ){
     sqlite3_memory_alarm(softHeapLimitEnforcer, 0, iLimit);
   }else{
@@ -85,6 +86,18 @@ static struct {
   void *alarmArg;
   int alarmBusy;
 
+  /*
+  ** Pointers to the end of sqlite3Config.pScratch and
+  ** sqlite3Config.pPage to a block of memory that records
+  ** which pages are available.
+  */
+  u32 *aScratchFree;
+  u32 *aPageFree;
+
+  /* Number of free pages for scratch and page-cache memory */
+  u32 nScratchFree;
+  u32 nPageFree;
+
   /*
   ** Performance statistics
   */
@@ -102,9 +115,29 @@ int sqlite3MallocInit(void){
     sqlite3MemSetDefault();
   }
   memset(&mem0, 0, sizeof(mem0));
-  if( sqlite3Config.bMemstat ){
+  if( sqlite3Config.bCoreMutex ){
     mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
   }
+  if( sqlite3Config.pScratch && sqlite3Config.szScratch>=3000
+      && sqlite3Config.nScratch>0 ){
+    int i;
+    mem0.aScratchFree = (u32*)&((char*)sqlite3Config.pScratch)
+                  [sqlite3Config.szScratch*sqlite3Config.nScratch];
+    for(i=0; i<sqlite3Config.nScratch; i++){ mem0.aScratchFree[i] = i; }
+    mem0.nScratchFree = sqlite3Config.nScratch;
+  }else{
+    sqlite3Config.pScratch = 0;
+  }
+  if( sqlite3Config.pPage && sqlite3Config.szPage>=512
+      && sqlite3Config.nPage>0 ){
+    int i;
+    mem0.aPageFree = (u32*)&((char*)sqlite3Config.pPage)
+                  [sqlite3Config.szPage*sqlite3Config.nPage];
+    for(i=0; i<sqlite3Config.nPage; i++){ mem0.aPageFree[i] = i; }
+    mem0.nPageFree = sqlite3Config.nPage;
+  }else{
+    sqlite3Config.pPage = 0;
+  }
   return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
 }
 
@@ -112,7 +145,8 @@ int sqlite3MallocInit(void){
 ** Deinitialize the memory allocation subsystem.
 */
 void sqlite3MallocEnd(void){
-   sqlite3Config.m.xShutdown(sqlite3Config.m.pAppData);
+  sqlite3Config.m.xShutdown(sqlite3Config.m.pAppData);
+  memset(&mem0, 0, sizeof(mem0));
 }
 
 /*
@@ -120,6 +154,7 @@ void sqlite3MallocEnd(void){
 */
 sqlite3_int64 sqlite3_memory_used(void){
   sqlite3_int64 n;
+  sqlite3_initialize();
   sqlite3_mutex_enter(mem0.mutex);
   n = mem0.nowUsed;
   sqlite3_mutex_leave(mem0.mutex);  
@@ -133,6 +168,7 @@ sqlite3_int64 sqlite3_memory_used(void){
 */
 sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
   sqlite3_int64 n;
+  sqlite3_initialize();
   sqlite3_mutex_enter(mem0.mutex);
   n = mem0.mxUsed;
   if( resetFlag ){
@@ -252,27 +288,55 @@ void *sqlite3ScratchMalloc(int n){
   if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
     return 0;
   }
+
 #if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+  /* Verify that no more than one scratch allocation per thread
+  ** is outstanding at one time.  (This is only checked in the
+  ** single-threaded case since checking in the multi-threaded case
+  ** would be much more complicated.) */
   assert( scratchAllocOut==0 );
   scratchAllocOut = 1;
 #endif
-  if( sqlite3Config.bMemstat ){
-    sqlite3_mutex_enter(mem0.mutex);
-    if( n>mem0.mxScratchReq ) mem0.mxScratchReq = n;
+
+  sqlite3_mutex_enter(mem0.mutex);
+  if( n>mem0.mxScratchReq ) mem0.mxScratchReq = n;
+  if( mem0.nScratchFree==0 || sqlite3Config.szScratch>=n ){
     p = sqlite3Config.m.xMalloc(n);
-    sqlite3_mutex_leave(mem0.mutex);
   }else{
-    p = sqlite3Config.m.xMalloc(n);
+    int i;
+    i = mem0.aScratchFree[--mem0.nScratchFree];
+    i *= sqlite3Config.szScratch;
+    p = (void*)&((char*)sqlite3Config.pScratch)[i];
   }
+  sqlite3_mutex_leave(mem0.mutex);
   return p;
 }
 void sqlite3ScratchFree(void *p){
   if( p ){
+
 #if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
+    /* Verify that no more than one scratch allocation per thread
+    ** is outstanding at one time.  (This is only checked in the
+    ** single-threaded case since checking in the multi-threaded case
+    ** would be much more complicated.) */
     assert( scratchAllocOut==1 );
     scratchAllocOut = 0;
 #endif
-    sqlite3Config.m.xFree(p);
+
+    if( sqlite3Config.pScratch==0
+       || p<sqlite3Config.pScratch
+       || p>=(void*)mem0.aScratchFree ){
+      sqlite3Config.m.xFree(p);
+    }else{
+      int i;
+      sqlite3_mutex_enter(mem0.mutex);
+      assert( mem0.nScratchFree<sqlite3Config.nScratch );
+      i = p - sqlite3Config.pScratch;
+      i /= sqlite3Config.szScratch;
+      assert( i>=0 && i<sqlite3Config.nScratch );
+      mem0.aScratchFree[mem0.nScratchFree++] = i;
+      sqlite3_mutex_leave(mem0.mutex);
+    }
   }
 }
 
index 737904db9f1c43edf1c9c6e2029136f716ed302c..b14d32bfba12d09266ca0bcab9cdbdbf8e016272 100644 (file)
@@ -30,7 +30,7 @@
 ** the version number) and changes its name to "sqlite3.h" as
 ** part of the build process.
 **
-** @(#) $Id: sqlite.h.in,v 1.334 2008/06/18 13:47:04 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.335 2008/06/18 18:12:04 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -1055,8 +1055,9 @@ struct sqlite3_mem_methods {
 ** <dt>SQLITE_CONFIG_SCRATCH</dt>
 ** <dd>This option specifies a static memory buffer that SQLite can use for
 ** scratch memory.  There are three arguments:  A pointer to the memory, the
-** size of each scratch buffer (sz), and the number of buffers (N).  The first
-** argument should point to an allocation of at least sz*N bytes of memory.
+** size of each scratch buffer (sz), and the number of buffers (N).  The sz
+** argument must be a multiple of 16. The first
+** argument should point to an allocation of at least (sz+1)*N bytes of memory.
 ** SQLite will use no more than one scratch buffer at once per thread, so
 ** N should be set to the expected maximum number of threads.  The sz 
 ** parameter should be 6 times the size of the largest database page size.
@@ -1070,8 +1071,9 @@ struct sqlite3_mem_methods {
 ** <dd>This option specifies a static memory buffer that SQLite can use for
 ** the database page cache.  There are three arguments:
 ** A pointer to the memory, the
-** size of each page buffer (sz), and the number of pages (N).  The first
-** argument should point to an allocation of at least sz*N bytes of memory.
+** size of each page buffer (sz), and the number of pages (N).  The sz
+** argument must be a power of two between 512 and 32768.  The first
+** argument should point to an allocation of at least (sz+4)*N bytes of memory.
 ** SQLite will use the memory provided by the first argument to satisfy
 ** its memory needs for the first N pages that it adds to cache.  If 
 ** additional page cache memory is needed beyond what is provided by
index da2a7b5f9951bbc22d5dfd202a85f17d482549b3..95ee365616e9d6a766979422861e6db17fc3c9ce 100644 (file)
@@ -13,7 +13,7 @@
 ** This file contains code used to implement test interfaces to the
 ** memory allocation subsystem.
 **
-** $Id: test_malloc.c,v 1.23 2008/05/29 02:57:48 shane Exp $
+** $Id: test_malloc.c,v 1.24 2008/06/18 18:12:04 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -651,6 +651,85 @@ static int test_memdebug_log(
   return TCL_OK;
 }
 
+/*
+** Usage:    sqlite3_config_scratch SIZE N
+**
+** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH.
+** The buffer is static and is of limited size.  N might be
+** adjusted downward as needed to accomodate the requested size.
+** The revised value of N is returned.
+**
+** A negative SIZE causes the buffer pointer to be NULL.
+*/
+static int test_config_scratch(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  int sz, N, rc;
+  Tcl_Obj *pResult;
+  static char buf[20000];
+  if( objc!=3 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
+    return TCL_ERROR;
+  }
+  if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR;
+  if( Tcl_GetIntFromObj(interp, objv[3], &N) ) return TCL_ERROR;
+  if( sz<0 ){
+    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0);
+  }else if( sz==0 ){
+    int mx = sizeof(buf)/(sz+4);
+    if( N>mx ) N = mx;
+    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N);
+  }
+  pResult = Tcl_NewObj();
+  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
+  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
+  Tcl_SetObjResult(interp, pResult);
+  return TCL_OK;
+}
+
+/*
+** Usage:    sqlite3_config_pagecache SIZE N
+**
+** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
+** The buffer is static and is of limited size.  N might be
+** adjusted downward as needed to accomodate the requested size.
+** The revised value of N is returned.
+**
+** A negative SIZE causes the buffer pointer to be NULL.
+*/
+static int test_config_pagecache(
+  void * clientData,
+  Tcl_Interp *interp,
+  int objc,
+  Tcl_Obj *CONST objv[]
+){
+  int sz, N, rc;
+  Tcl_Obj *pResult;
+  static char buf[100000];
+  if( objc!=3 ){
+    Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
+    return TCL_ERROR;
+  }
+  if( Tcl_GetIntFromObj(interp, objv[2], &sz) ) return TCL_ERROR;
+  if( Tcl_GetIntFromObj(interp, objv[3], &N) ) return TCL_ERROR;
+  if( sz<0 ){
+    rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0);
+  }else if( sz==0 ){
+    int mx = sizeof(buf)/(sz+4);
+    if( N>mx ) N = mx;
+    rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
+  }
+  pResult = Tcl_NewObj();
+  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
+  Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
+  Tcl_SetObjResult(interp, pResult);
+  return TCL_OK;
+}
+
+
 /*
 ** Register commands with the TCL interpreter.
 */
@@ -672,7 +751,9 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
      { "sqlite3_memdebug_pending",   test_memdebug_pending         },
      { "sqlite3_memdebug_settitle",  test_memdebug_settitle        },
      { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count },
-     { "sqlite3_memdebug_log",       test_memdebug_log },
+     { "sqlite3_memdebug_log",       test_memdebug_log             },
+     { "sqlite3_config_scratch",     test_config_scratch           },
+     { "sqlite3_config_pagecache",   test_config_pagecache         },
   };
   int i;
   for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){