From 7e828035d9a2238afeac10838beff2e947d899f9 Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Sat, 26 May 2007 19:50:00 +0000 Subject: CarpetLib: Add class mempool A mempool (memory pool) is a large chunk of memory. You can allocate pieces of it. In order to simplify things there is no way to free a piece again. If the mempool is destroyed, then all its memory is freed. This is dangerous: you have to make sure that no one continues to use that memory afterwards. Using a memory pool for short-lived objects can reduce memory fragmentation. darcs-hash:20070526195001-dae7b-b419df094d19b85dbf145debdf62da2dc57823af.gz --- Carpet/CarpetLib/src/mem.cc | 55 +++++++++++++++++++++++++++++++++++++++++++++ Carpet/CarpetLib/src/mem.hh | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/Carpet/CarpetLib/src/mem.cc b/Carpet/CarpetLib/src/mem.cc index a983fc497..f53a9ccd0 100644 --- a/Carpet/CarpetLib/src/mem.cc +++ b/Carpet/CarpetLib/src/mem.cc @@ -135,6 +135,61 @@ has_clients () const +size_t const mempool::chunksize; +size_t const mempool::align; + +mempool:: +mempool () + : freeptr (0), freesize (0) +{ +} + +mempool:: +~mempool () +{ + while (not chunks.empty()) { + free (chunks.top()); + chunks.pop(); + } +} + +void * +mempool:: +alloc (size_t nbytes) +{ + // Take a shortcut for silly requests + if (nbytes == 0) return 0; + + // Round up request size + nbytes = (nbytes + align - 1) / align * align; + + // If there is not enough memory left, allocate a new chunk. Ignore + // whatever is left in the old chunk. + if (nbytes > freesize) { + // Allocate the usual chunk size, or more if more is requested + freesize = max (chunksize, nbytes); + freeptr = malloc (freesize); + if (not freeptr) { + CCTK_VWarn (CCTK_WARN_ABORT, __LINE__, __FILE__, CCTK_THORNSTRING, + "Failed to allocate %.3f MB of memory", + double(freesize/1.0e6)); + } + // Remember the pointer so that it can be freed + chunks.push (freeptr); + } + + // Allocate a piece from the current chunk + void * const ptr = freeptr; + assert (freesize >= nbytes); + freesize -= nbytes; + assert (freeptr); + freeptr = static_cast (freeptr) + nbytes; + + return ptr; +} + + + extern "C" void CarpetLib_printmemstats (CCTK_ARGUMENTS); void CarpetLib_printmemstats (CCTK_ARGUMENTS) diff --git a/Carpet/CarpetLib/src/mem.hh b/Carpet/CarpetLib/src/mem.hh index 7ccbd6d72..b38d5459b 100644 --- a/Carpet/CarpetLib/src/mem.hh +++ b/Carpet/CarpetLib/src/mem.hh @@ -2,6 +2,7 @@ #define MEM_HH #include +#include #include using namespace std; @@ -34,4 +35,44 @@ public: bool has_clients () const; }; + + +// A mempool (memory pool) is a large chunk of memory. You can +// allocate pieces of it. In order to simplify things there is no way +// to free a piece again. If the mempool is destroyed, then all its +// memory is freed. This is dangerous: you have to make sure that no +// one continues to use that memory afterwards. Using a memory pool +// for short-lived objects can reduce memory fragmentation. +class mempool +{ + // The minimum chunk size which is requested via malloc. If a + // larger piece is required, then a larger chunk is allocated. + static size_t const chunksize = 10 * 1024 * 1024; + // The alignment of the returned memory. All requests are rounded + // up to the next multiple of this alignment. + static size_t const align = 32; + + // List of all allocated chunks. When the mempool is destroyed, + // these pointers need to be freed. + stack chunks; + + // Pointer to the beginning of some unused memory + void * freeptr; + // Size of that unused memory + size_t freesize; + +private: + // Forbid copying + mempool (mempool const &); +public: + + // Create and destroy a memory pool + mempool (); + ~mempool (); + + // Allocate some memory and return a pointer to it. This cannot + // fail. + void * alloc (size_t nbytes); +}; + #endif // ifndef MEM_HH -- cgit v1.2.3