aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordanielk1977 <danielk1977@noemail.net>2008-07-25 08:48:59 +0000
committerdanielk1977 <danielk1977@noemail.net>2008-07-25 08:48:59 +0000
commit31fab4f30bfe449c7c80bb61d8d68956ad00fe45 (patch)
tree0c595c238d0c92d69635fb9b1338a25fe20ed96d /src
parent2abcd58f09da0d98118c4a2d2cb78f40dbc6a2ca (diff)
downloadsqlite-31fab4f30bfe449c7c80bb61d8d68956ad00fe45.tar.gz
sqlite-31fab4f30bfe449c7c80bb61d8d68956ad00fe45.zip
Updates to mem6.c allocator. (CVS 5473)
FossilOrigin-Name: 43a4cae2acea33d1a17c0037516e9c27fb7e8e91
Diffstat (limited to 'src')
-rw-r--r--src/main.c3
-rw-r--r--src/mem1.c4
-rw-r--r--src/mem2.c4
-rw-r--r--src/mem6.c81
-rw-r--r--src/sqlite.h.in5
-rw-r--r--src/sqliteInt.h5
-rw-r--r--src/test_malloc.c10
7 files changed, 84 insertions, 28 deletions
diff --git a/src/main.c b/src/main.c
index 8cd1d6414..cf5587839 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.481 2008/07/24 08:20:40 danielk1977 Exp $
+** $Id: main.c,v 1.482 2008/07/25 08:49:00 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -269,6 +269,7 @@ int sqlite3_config(int op, ...){
#if defined(SQLITE_ENABLE_MEMSYS6)
case SQLITE_CONFIG_CHUNKALLOC: {
+ sqlite3Config.nSmall = va_arg(ap, int);
sqlite3Config.m = *sqlite3MemGetMemsys6();
break;
}
diff --git a/src/mem1.c b/src/mem1.c
index 359ce5d8c..1a3a68eb0 100644
--- a/src/mem1.c
+++ b/src/mem1.c
@@ -17,7 +17,7 @@
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
-** $Id: mem1.c,v 1.24 2008/07/24 08:20:40 danielk1977 Exp $
+** $Id: mem1.c,v 1.25 2008/07/25 08:49:00 danielk1977 Exp $
*/
#include "sqliteInt.h"
@@ -120,7 +120,7 @@ static void sqlite3MemShutdown(void *NotUsed){
return;
}
-sqlite3_mem_methods *sqlite3MemGetDefault(void){
+const sqlite3_mem_methods *sqlite3MemGetDefault(void){
static const sqlite3_mem_methods defaultMethods = {
sqlite3MemMalloc,
sqlite3MemFree,
diff --git a/src/mem2.c b/src/mem2.c
index 33c8cfeff..f1425e8ce 100644
--- a/src/mem2.c
+++ b/src/mem2.c
@@ -19,7 +19,7 @@
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
-** $Id: mem2.c,v 1.36 2008/07/24 23:34:07 drh Exp $
+** $Id: mem2.c,v 1.37 2008/07/25 08:49:00 danielk1977 Exp $
*/
#include "sqliteInt.h"
@@ -324,7 +324,7 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
}
-sqlite3_mem_methods *sqlite3MemGetDefault(void){
+const sqlite3_mem_methods *sqlite3MemGetDefault(void){
static const sqlite3_mem_methods defaultMethods = {
sqlite3MemMalloc,
sqlite3MemFree,
diff --git a/src/mem6.c b/src/mem6.c
index bf1724c40..7903c08b3 100644
--- a/src/mem6.c
+++ b/src/mem6.c
@@ -10,19 +10,52 @@
**
*************************************************************************
**
-** $Id: mem6.c,v 1.2 2008/07/24 10:11:28 danielk1977 Exp $
+** This file contains an alternative memory allocation system for SQLite.
+** This system is implemented as a wrapper around the default memory
+** allocation system (usually the one found in mem1.c - system malloc).
+**
+** This system differentiates between requests for "small" allocations
+** (by default those of 128 bytes or less) and "large" allocations (all
+** others). The 256 byte threshhold is configurable at runtime.
+**
+** All requests for large allocations are passed through to the
+** default memory allocation system.
+**
+** Requests for small allocations are met by allocating space within
+** one or more larger "chunks" of memory obtained from the default
+** memory allocation system. Chunks of memory are usually 64KB or
+** larger. The algorithm used to manage space within each chunk is
+** the same as that used by mem5.c.
+**
+** This strategy is designed to prevent the default memory allocation
+** system (usually the system malloc) from suffering from heap
+** fragmentation. On some systems, heap fragmentation can cause a
+** significant real-time slowdown.
+**
+** $Id: mem6.c,v 1.3 2008/07/25 08:49:00 danielk1977 Exp $
*/
#ifdef SQLITE_ENABLE_MEMSYS6
+#include "sqliteInt.h"
+
/*
-** Maximum size of any allocation is ((1<<LOGMAX)*Mem6Chunk.nAtom). Since
-** Mem6Chunk.nAtom is always at least 8, this is not really a practical
-** limitation.
+** Maximum size of any "small" allocation is ((1<<LOGMAX)*Mem6Chunk.nAtom).
+** Mem6Chunk.nAtom is always at least 8, so this is not a practical
+** limitation
*/
#define LOGMAX 30
-#include "sqliteInt.h"
+/*
+** Default value for the "small" allocation size threshold.
+*/
+#define SMALL_MALLOC_DEFAULT_THRESHOLD 256
+
+/*
+** Minimum size for a memory chunk.
+*/
+#define MIN_CHUNKSIZE (1<<16)
+
typedef struct Mem6Chunk Mem6Chunk;
typedef struct Mem6Link Mem6Link;
@@ -278,12 +311,9 @@ static Mem6Chunk *chunkInit(u8 *zChunk, int nChunk, int nMinAlloc){
struct Mem6Global {
sqlite3_mem_methods parent; /* Used to allocate chunks */
- int nChunkSize; /* Size of each chunk, in bytes. */
int nMinAlloc; /* Minimum allowed allocation size */
-
+ int nThreshold; /* Allocs larger than this go to parent */
sqlite3_mutex *mutex;
-
- /* This data structure will be fixed... */
Mem6Chunk *pChunk; /* Singly linked list of all memory chunks */
} mem6;
@@ -297,6 +327,22 @@ static void mem6Leave(void){
}
/*
+** Based on the number and size of the currently allocated chunks, return
+** the size of the next chunk to allocate, in bytes.
+*/
+static int nextChunkSize(void){
+ int iTotal = 0;
+ Mem6Chunk *p;
+ for(p=mem6.pChunk; p; p=p->pNext){
+ iTotal += mem6.parent.xSize((void *)p);
+ }
+ if( iTotal==0 ){
+ iTotal = MIN_CHUNKSIZE;
+ }
+ return iTotal;
+}
+
+/*
** The argument is a pointer that may or may not have been allocated from
** one of the Mem6Chunk objects managed within mem6. If it is, return
** a pointer to the owner chunk. If not, return 0.
@@ -323,7 +369,7 @@ static void *memsys6Malloc(int nByte){
void *p = 0;
mem6Enter();
- if( nByte>=mem6.nChunkSize/3 ){
+ if( nByte>mem6.nThreshold ){
p = mem6.parent.xMalloc(nByte);
}else{
for(pChunk=mem6.pChunk; !p && pChunk; pChunk=pChunk->pNext){
@@ -331,9 +377,10 @@ static void *memsys6Malloc(int nByte){
}
if( !p ){
- p = mem6.parent.xMalloc(mem6.nChunkSize);
+ int iSize = nextChunkSize();
+ p = mem6.parent.xMalloc(iSize);
if( p ){
- pChunk = chunkInit((u8 *)p, mem6.nChunkSize, mem6.nMinAlloc);
+ pChunk = chunkInit((u8 *)p, iSize, mem6.nMinAlloc);
pChunk->pNext = mem6.pChunk;
mem6.pChunk = pChunk;
p = chunkMalloc(pChunk, nByte);
@@ -398,10 +445,12 @@ static int memsys6Roundup(int n){
static int memsys6Init(void *pCtx){
u8 bMemstat = sqlite3Config.bMemstat;
mem6.parent = *sqlite3MemGetDefault();
- mem6.nChunkSize = (1<<16);
mem6.nMinAlloc = 16;
mem6.pChunk = 0;
-
+ mem6.nThreshold = sqlite3Config.nSmall;
+ if( mem6.nThreshold<=0 ){
+ mem6.nThreshold = SMALL_MALLOC_DEFAULT_THRESHOLD;
+ }
if( !bMemstat ){
mem6.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
@@ -419,6 +468,10 @@ static int memsys6Init(void *pCtx){
}
static void memsys6Shutdown(void *pCtx){
+ if( mem6.parent.xShutdown ){
+ mem6.parent.xShutdown(mem6.parent.pAppData);
+ }
+ memset(&mem6, 0, sizeof(mem6));
}
/*
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 3a7f1a220..246ba6ea8 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -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.378 2008/07/24 08:20:40 danielk1977 Exp $
+** @(#) $Id: sqlite.h.in,v 1.379 2008/07/25 08:49:00 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@@ -1157,8 +1157,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
-
-#define SQLITE_CONFIG_CHUNKALLOC 12 /* nil */
+#define SQLITE_CONFIG_CHUNKALLOC 12 /* int threshold */
/*
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 28d6176d5..45cbdfdb6 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.744 2008/07/24 08:20:40 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.745 2008/07/25 08:49:00 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -1789,6 +1789,7 @@ struct Sqlite3Config {
int isInit; /* True after initialization has finished */
int isMallocInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
+ int nSmall; /* alloc size threshold used by mem6.c */
};
/*
@@ -1841,7 +1842,7 @@ void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);
-sqlite3_mem_methods *sqlite3MemGetDefault(void);
+const sqlite3_mem_methods *sqlite3MemGetDefault(void);
const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
const sqlite3_mem_methods *sqlite3MemGetMemsys6(void);
diff --git a/src/test_malloc.c b/src/test_malloc.c
index 30df0348f..ea5c2d6c7 100644
--- a/src/test_malloc.c
+++ b/src/test_malloc.c
@@ -13,7 +13,7 @@
** This file contains code used to implement test interfaces to the
** memory allocation subsystem.
**
-** $Id: test_malloc.c,v 1.39 2008/07/24 08:20:40 danielk1977 Exp $
+** $Id: test_malloc.c,v 1.40 2008/07/25 08:49:00 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -967,11 +967,13 @@ static int test_config_chunkalloc(
Tcl_Obj *CONST objv[]
){
int rc;
- if( objc!=1 ){
- Tcl_WrongNumArgs(interp, 1, objv, "");
+ int nThreshold;
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "THRESHOLD");
return TCL_ERROR;
}
- rc = sqlite3_config(SQLITE_CONFIG_CHUNKALLOC);
+ if( Tcl_GetIntFromObj(interp, objv[1], &nThreshold) ) return TCL_ERROR;
+ rc = sqlite3_config(SQLITE_CONFIG_CHUNKALLOC, nThreshold);
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
return TCL_OK;
}