From 1528b64a68f3144b9b321efefb22800a52e64dd4 Mon Sep 17 00:00:00 2001 From: rubidium Date: Wed, 21 Oct 2009 19:38:50 +0000 Subject: (svn r17839) -Codechange: implement the concept of 'caching' pool items to pools, that is instead of 'free' push the unused items in a linked list and use them on 'malloc'. Also add the concept of zeroing, or actually not zeroing, on new for pool items. --- src/core/pool_func.hpp | 36 +++++++++++++++++++++++++++++++----- src/core/pool_type.hpp | 19 +++++++++++++++++-- 2 files changed, 48 insertions(+), 7 deletions(-) (limited to 'src/core') diff --git a/src/core/pool_func.hpp b/src/core/pool_func.hpp index 567ef1ae9..68ee378b3 100644 --- a/src/core/pool_func.hpp +++ b/src/core/pool_func.hpp @@ -17,8 +17,8 @@ #include "pool_type.hpp" #define DEFINE_POOL_METHOD(type) \ - template \ - type Pool + template \ + type Pool DEFINE_POOL_METHOD(inline)::Pool(const char *name) : name(name), @@ -27,7 +27,8 @@ DEFINE_POOL_METHOD(inline)::Pool(const char *name) : first_unused(0), items(0), cleaning(false), - data(NULL) + data(NULL), + alloc_cache(NULL) { } DEFINE_POOL_METHOD(inline void)::ResizeFor(size_t index) @@ -75,7 +76,18 @@ DEFINE_POOL_METHOD(inline void *)::AllocateItem(size_t size, size_t index) this->first_unused = max(this->first_unused, index + 1); this->items++; - Titem *item = this->data[index] = (Titem *)CallocT(size); + Titem *item; + if (Tcache && this->alloc_cache != NULL) { + assert(sizeof(Titem) == size); + item = (Titem *)this->alloc_cache; + this->alloc_cache = this->alloc_cache->next; + if (Tzero) MemSetT(item, 0); + } else if (Tzero) { + item = (Titem *)CallocT(size); + } else { + item = (Titem *)MallocT(size); + } + this->data[index] = item; item->index = (uint)index; return item; } @@ -111,7 +123,13 @@ DEFINE_POOL_METHOD(void)::FreeItem(size_t index) { assert(index < this->size); assert(this->data[index] != NULL); - free(this->data[index]); + if (Tcache) { + AllocCache *ac = (AllocCache *)this->data[index]; + ac->next = this->alloc_cache; + this->alloc_cache = ac; + } else { + free(this->data[index]); + } this->data[index] = NULL; this->first_free = min(this->first_free, index); this->items--; @@ -129,6 +147,14 @@ DEFINE_POOL_METHOD(void)::CleanPool() this->first_unused = this->first_free = this->size = 0; this->data = NULL; this->cleaning = false; + + if (Tcache) { + while (this->alloc_cache != NULL) { + AllocCache *ac = this->alloc_cache; + this->alloc_cache = ac->next; + free(ac); + } + } } #undef DEFINE_POOL_METHOD diff --git a/src/core/pool_type.hpp b/src/core/pool_type.hpp index 728678515..58a58f6ac 100644 --- a/src/core/pool_type.hpp +++ b/src/core/pool_type.hpp @@ -18,8 +18,11 @@ * @tparam Tindex Type of the index for this pool * @tparam Tgrowth_step Size of growths; if the pool is full increase the size by this amount * @tparam Tmax_size Maximum size of the pool + * @tparam Tcache Whether to perform 'alloc' caching, i.e. don't actually free/malloc just reuse the memory + * @tparam Tzero Whether to zero the memory + * @warning when Tcache is enabled *all* instances of this pool's item must be of the same size. */ -template +template struct Pool { static const size_t MAX_SIZE = Tmax_size; ///< Make template parameter accessible from outside @@ -75,7 +78,7 @@ struct Pool { * Base class for all PoolItems * @tparam Tpool The pool this item is going to be part of */ - template *Tpool> + template *Tpool> struct PoolItem { Tindex index; ///< Index of this pool item @@ -252,6 +255,18 @@ struct Pool { private: static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t); ///< Contant to indicate we can't allocate any more items + /** + * Helper struct to cache 'freed' PoolItems so we + * do not need to allocate them again. + */ + struct AllocCache { + /** The next in our 'cache' */ + AllocCache *next; + }; + + /** Cache of freed pointers */ + AllocCache *alloc_cache; + /** * Makes given index valid * @param size size of item -- cgit v1.2.3-54-g00ecf