diff options
author | 2019-02-21 22:59:17 +0100 | |
---|---|---|
committer | 2019-02-22 08:18:01 +0100 | |
commit | cf73ccc764d574284bef4ce95ee5bc3e9089f053 (patch) | |
tree | 1655c2836b200c90d5fe5dd5833159e7e8be1522 /src/lib/netlist/plib/pmempool.h | |
parent | 6ed352261d40e37887357fe901dc380d6ef79844 (diff) |
netlist: memory management. [Couriersud]
Memory management in plib is now alignment-aware. All allocations
respect c++11 alignas. Selected classes like parray and aligned_vector
also provide hints (__builtin_assume_aligned) to g++ and clang.
The alignment optimizations have little impact on the current use cases.
They only become effective on bigger data processing.
What has a measurable impact is memory pooling. This speeds up netlist
games like breakout and pong by about 5%.
Tested with linux, macosx and windows cross builds. All features are
disabled since I can not rule out they may temporarily break more exotic
builds.
Diffstat (limited to 'src/lib/netlist/plib/pmempool.h')
-rw-r--r-- | src/lib/netlist/plib/pmempool.h | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/src/lib/netlist/plib/pmempool.h b/src/lib/netlist/plib/pmempool.h index 80e30ada324..c55d66d8847 100644 --- a/src/lib/netlist/plib/pmempool.h +++ b/src/lib/netlist/plib/pmempool.h @@ -34,7 +34,6 @@ namespace plib { void operator()(T *p) const { - p->~T(); P::free(p); } }; @@ -83,7 +82,7 @@ namespace plib { block * new_block(std::size_t min_bytes) { - auto *b = new block(this, min_bytes); + auto *b = plib::pnew<block>(this, min_bytes); m_blocks.push_back(b); return b; } @@ -123,22 +122,27 @@ namespace plib { } } - void *alloc(size_t size, size_t align) + template <std::size_t ALIGN> + void *alloc(size_t size) { + size_t align = ALIGN; if (align < m_min_align) align = m_min_align; - size_t rs = (size + align - 1) & ~(align - 1); + size_t rs = size + align; for (auto &b : m_blocks) { if (b->m_free > rs) { b->m_free -= rs; b->m_num_alloc++; - auto ret = reinterpret_cast<void *>(b->m_data + b->m_cur); + auto *ret = reinterpret_cast<void *>(b->m_data + b->m_cur); auto capacity(rs); - std::align(align, size, ret, capacity); + ret = std::align(align, size, ret, capacity); + if (ret == nullptr) + printf("Oh no\n"); sinfo().insert({ ret, info(b, b->m_cur)}); + rs -= (capacity - size); b->m_cur += rs; return ret; @@ -148,17 +152,24 @@ namespace plib { block *b = new_block(rs); b->m_num_alloc = 1; b->m_free = m_min_alloc - rs; - auto ret = reinterpret_cast<void *>(b->m_data + b->m_cur); + auto *ret = reinterpret_cast<void *>(b->m_data + b->m_cur); auto capacity(rs); - std::align(align, size, ret, capacity); + ret = std::align(align, size, ret, capacity); + if (ret == nullptr) + printf("Oh no\n"); sinfo().insert({ ret, info(b, b->m_cur)}); + rs -= (capacity - size); b->m_cur += rs; return ret; } } - static void free(void *ptr) + template <typename T> + static void free(T *ptr) { + /* call destructor */ + ptr->~T(); + auto it = sinfo().find(ptr); if (it == sinfo().end()) plib::terminate("mempool::free - pointer not found\n"); @@ -182,7 +193,7 @@ namespace plib { template<typename T, typename... Args> poolptr<T> make_poolptr(Args&&... args) { - auto mem = this->alloc(sizeof(T), alignof(T)); + auto *mem = this->alloc<alignof(T)>(sizeof(T)); auto *obj = new (mem) T(std::forward<Args>(args)...); poolptr<T> a(obj, true); return std::move(a); @@ -208,6 +219,7 @@ namespace plib { ~mempool_default() = default; +#if 0 void *alloc(size_t size) { plib::unused_var(m_min_alloc); // -Wunused-private-field fires without @@ -216,9 +228,11 @@ namespace plib { return ::operator new(size); } - static void free(void *ptr) +#endif + template <typename T> + static void free(T *ptr) { - ::operator delete(ptr); + plib::pdelete(ptr); } template <typename T> @@ -227,12 +241,13 @@ namespace plib { template<typename T, typename... Args> poolptr<T> make_poolptr(Args&&... args) { - auto mem(alloc(sizeof(T))); - auto *obj = new (mem) T(std::forward<Args>(args)...); + plib::unused_var(m_min_alloc); // -Wunused-private-field fires without + plib::unused_var(m_min_align); + + auto *obj = plib::pnew<T>(std::forward<Args>(args)...); poolptr<T> a(obj, true); return std::move(a); } - }; |