X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmempool.c;h=f02703a31fa2b41e83600a8099d668f944931f13;hb=aa3de31b70d1c5826d67147696423cdd9c334d41;hp=69f7c6a27cb0c319a1b195b301ad9025874573f7;hpb=669beaed8380fa592533c8755f72593b4422d01d;p=mono.git diff --git a/mono/metadata/mempool.c b/mono/metadata/mempool.c index 69f7c6a27cb..f02703a31fa 100644 --- a/mono/metadata/mempool.c +++ b/mono/metadata/mempool.c @@ -7,7 +7,9 @@ * Author: * Dietmar Maurer (dietmar@ximian.com) * - * (C) 2001 Ximian, Inc. + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) + * Copyright 2011 Xamarin Inc. (http://www.xamarin.com) */ #include @@ -15,6 +17,11 @@ #include #include "mempool.h" +#include "mempool-internals.h" + +#if USE_MALLOC_FOR_MEMPOOLS +#define MALLOC_ALLOCATION +#endif /* * MonoMemPool is for fast allocation of memory. We free @@ -22,14 +29,33 @@ */ #define MEM_ALIGN 8 +#define ALIGN_SIZE(s) (((s) + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1)) +#define SIZEOF_MEM_POOL (ALIGN_SIZE (sizeof (MonoMemPool))) +#if MONO_SMALL_CONFIG +#define MONO_MEMPOOL_PAGESIZE 4096 +#define MONO_MEMPOOL_MINSIZE 256 +#else #define MONO_MEMPOOL_PAGESIZE 8192 +#define MONO_MEMPOOL_MINSIZE 512 +#endif #ifndef G_LIKELY #define G_LIKELY(a) (a) #define G_UNLIKELY(a) (a) #endif +#ifdef MALLOC_ALLOCATION +typedef struct _Chunk { + struct _Chunk *next; + guint32 size; +} Chunk; + +struct _MonoMemPool { + Chunk *chunks; + guint32 allocated; +}; +#else struct _MonoMemPool { MonoMemPool *next; gint rest; @@ -40,6 +66,9 @@ struct _MonoMemPool { guint32 allocated; } d; }; +#endif + +static long total_bytes_allocated = 0; /** * mono_mempool_new: @@ -47,15 +76,29 @@ struct _MonoMemPool { * Returns: a new memory pool. */ MonoMemPool * -mono_mempool_new () +mono_mempool_new (void) +{ + return mono_mempool_new_size (MONO_MEMPOOL_PAGESIZE); +} + +MonoMemPool * +mono_mempool_new_size (int initial_size) { - MonoMemPool *pool = g_malloc (MONO_MEMPOOL_PAGESIZE); +#ifdef MALLOC_ALLOCATION + return g_new0 (MonoMemPool, 1); +#else + MonoMemPool *pool; + if (initial_size < MONO_MEMPOOL_MINSIZE) + initial_size = MONO_MEMPOOL_MINSIZE; + pool = g_malloc (initial_size); pool->next = NULL; - pool->pos = (guint8*)pool + sizeof (MonoMemPool); - pool->end = pool->pos + MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool); - pool->d.allocated = pool->size = MONO_MEMPOOL_PAGESIZE; + pool->pos = (guint8*)pool + SIZEOF_MEM_POOL; + pool->end = pool->pos + initial_size - SIZEOF_MEM_POOL; + pool->d.allocated = pool->size = initial_size; + total_bytes_allocated += initial_size; return pool; +#endif } /** @@ -67,14 +110,22 @@ mono_mempool_new () void mono_mempool_destroy (MonoMemPool *pool) { +#ifdef MALLOC_ALLOCATION + mono_mempool_empty (pool); + + g_free (pool); +#else MonoMemPool *p, *n; + total_bytes_allocated -= pool->d.allocated; + p = pool; while (p) { n = p->next; g_free (p); p = n; } +#endif } /** @@ -86,6 +137,9 @@ mono_mempool_destroy (MonoMemPool *pool) void mono_mempool_invalidate (MonoMemPool *pool) { +#ifdef MALLOC_ALLOCATION + g_assert_not_reached (); +#else MonoMemPool *p, *n; p = pool; @@ -94,13 +148,28 @@ mono_mempool_invalidate (MonoMemPool *pool) memset (p, 42, p->size); p = n; } +#endif } void mono_mempool_empty (MonoMemPool *pool) { - pool->pos = (guint8*)pool + sizeof (MonoMemPool); - pool->end = pool->pos + MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool); +#ifdef MALLOC_ALLOCATION + Chunk *p, *n; + + p = pool->chunks; + pool->chunks = NULL; + while (p) { + n = p->next; + g_free (p); + p = n; + } + + pool->allocated = 0; +#else + pool->pos = (guint8*)pool + SIZEOF_MEM_POOL; + pool->end = pool->pos + pool->size - SIZEOF_MEM_POOL; +#endif } /** @@ -112,6 +181,9 @@ mono_mempool_empty (MonoMemPool *pool) void mono_mempool_stats (MonoMemPool *pool) { +#ifdef MALLOC_ALLOCATION + g_assert_not_reached (); +#else MonoMemPool *p; int count = 0; guint32 still_free = 0; @@ -128,11 +200,62 @@ mono_mempool_stats (MonoMemPool *pool) g_print ("Num chunks: %d\n", count); g_print ("Free memory: %d\n", still_free); } +#endif +} + +#ifndef MALLOC_ALLOCATION +#ifdef TRACE_ALLOCATIONS +#include +#include "metadata/appdomain.h" +#include "metadata/metadata-internals.h" + +static mono_mutex_t mempool_tracing_lock; +#define BACKTRACE_DEPTH 7 +static void +mono_backtrace (int size) +{ + void *array[BACKTRACE_DEPTH]; + char **names; + int i, symbols; + static gboolean inited; + + if (!inited) { + mono_mutex_init_recursive (&mempool_tracing_lock); + inited = TRUE; + } + + mono_mutex_lock (&mempool_tracing_lock); + g_print ("Allocating %d bytes\n", size); + symbols = backtrace (array, BACKTRACE_DEPTH); + names = backtrace_symbols (array, symbols); + for (i = 1; i < symbols; ++i) { + g_print ("\t%s\n", names [i]); + } + free (names); + mono_mutex_unlock (&mempool_tracing_lock); } +#endif + +static int +get_next_size (MonoMemPool *pool, int size) +{ + int target = pool->next? pool->next->size: pool->size; + size += SIZEOF_MEM_POOL; + /* increase the size */ + target += target / 2; + while (target < size) { + target += target / 2; + } + if (target > MONO_MEMPOOL_PAGESIZE && size <= MONO_MEMPOOL_PAGESIZE) + target = MONO_MEMPOOL_PAGESIZE; + return target; +} +#endif + /** * mono_mempool_alloc: - * @pool: the momory pool to destroy + * @pool: the momory pool to use * @size: size of the momory block * * Allocates a new block of memory in @pool. @@ -143,38 +266,60 @@ gpointer mono_mempool_alloc (MonoMemPool *pool, guint size) { gpointer rval; - - size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1); + size = ALIGN_SIZE (size); + +#ifdef MALLOC_ALLOCATION + { + Chunk *c = g_malloc (size + sizeof (Chunk)); + + c->next = pool->chunks; + pool->chunks = c; + c->size = size - sizeof(Chunk); + + pool->allocated += size; + + rval = ((guint8*)c) + sizeof (Chunk); + } +#else rval = pool->pos; pool->pos = (guint8*)rval + size; +#ifdef TRACE_ALLOCATIONS + if (pool == mono_get_corlib ()->mempool) { + mono_backtrace (size); + } +#endif if (G_UNLIKELY (pool->pos >= pool->end)) { pool->pos -= size; if (size >= 4096) { - MonoMemPool *np = g_malloc (sizeof (MonoMemPool) + size); + MonoMemPool *np = g_malloc (SIZEOF_MEM_POOL + size); np->next = pool->next; pool->next = np; - np->pos = (guint8*)np + sizeof (MonoMemPool); - np->size = sizeof (MonoMemPool) + size; - np->end = np->pos + np->size - sizeof (MonoMemPool); - pool->d.allocated += sizeof (MonoMemPool) + size; - return (guint8*)np + sizeof (MonoMemPool); + np->pos = (guint8*)np + SIZEOF_MEM_POOL; + np->size = SIZEOF_MEM_POOL + size; + np->end = np->pos + np->size - SIZEOF_MEM_POOL; + pool->d.allocated += SIZEOF_MEM_POOL + size; + total_bytes_allocated += SIZEOF_MEM_POOL + size; + return (guint8*)np + SIZEOF_MEM_POOL; } else { - MonoMemPool *np = g_malloc (MONO_MEMPOOL_PAGESIZE); + int new_size = get_next_size (pool, size); + MonoMemPool *np = g_malloc (new_size); np->next = pool->next; pool->next = np; - pool->pos = (guint8*)np + sizeof (MonoMemPool); - np->pos = (guint8*)np + sizeof (MonoMemPool); - np->size = MONO_MEMPOOL_PAGESIZE; + pool->pos = (guint8*)np + SIZEOF_MEM_POOL; + np->pos = (guint8*)np + SIZEOF_MEM_POOL; + np->size = new_size; np->end = np->pos; - pool->end = pool->pos + MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool); - pool->d.allocated += MONO_MEMPOOL_PAGESIZE; + pool->end = pool->pos + new_size - SIZEOF_MEM_POOL; + pool->d.allocated += new_size; + total_bytes_allocated += new_size; rval = pool->pos; pool->pos += size; } } +#endif return rval; } @@ -188,8 +333,11 @@ gpointer mono_mempool_alloc0 (MonoMemPool *pool, guint size) { gpointer rval; - - size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1); + +#ifdef MALLOC_ALLOCATION + rval = mono_mempool_alloc (pool, size); +#else + size = ALIGN_SIZE (size); rval = pool->pos; pool->pos = (guint8*)rval + size; @@ -197,6 +345,12 @@ mono_mempool_alloc0 (MonoMemPool *pool, guint size) if (G_UNLIKELY (pool->pos >= pool->end)) { rval = mono_mempool_alloc (pool, size); } +#ifdef TRACE_ALLOCATIONS + else if (pool == mono_get_corlib ()->mempool) { + mono_backtrace (size); + } +#endif +#endif memset (rval, 0, size); return rval; @@ -211,6 +365,19 @@ gboolean mono_mempool_contains_addr (MonoMemPool *pool, gpointer addr) { +#ifdef MALLOC_ALLOCATION + Chunk *c; + + c = pool->chunks; + while (c) { + guint8 *p = ((guint8*)c) + sizeof (Chunk); + + if (addr >= (gpointer)p && addr < (gpointer)(p + c->size)) + return TRUE; + + c = c->next; + } +#else MonoMemPool *p; p = pool; @@ -219,6 +386,7 @@ mono_mempool_contains_addr (MonoMemPool *pool, return TRUE; p = p->next; } +#endif return FALSE; } @@ -254,5 +422,20 @@ mono_mempool_strdup (MonoMemPool *pool, guint32 mono_mempool_get_allocated (MonoMemPool *pool) { +#ifdef MALLOC_ALLOCATION + return pool->allocated; +#else return pool->d.allocated; +#endif +} + +/** + * mono_mempool_get_bytes_allocated: + * + * Return the number of bytes currently allocated for mempools. + */ +long +mono_mempool_get_bytes_allocated (void) +{ + return total_bytes_allocated; }