diff --git a/include/pool_alloc.h b/include/pool_alloc.h old mode 100644 new mode 100755 index 3509a2d..8097441 --- a/include/pool_alloc.h +++ b/include/pool_alloc.h @@ -11,9 +11,8 @@ namespace mem { class IPC_EXPORT pool_alloc { public: - static void clear(); static void* alloc(std::size_t size); - static void free(void* p, std::size_t size); + static void free (void* p, std::size_t size); }; //////////////////////////////////////////////////////////////// diff --git a/performance.xlsx b/performance.xlsx index dbbccb1..a9785b0 100644 Binary files a/performance.xlsx and b/performance.xlsx differ diff --git a/src/memory/alloc.h b/src/memory/alloc.h old mode 100644 new mode 100755 index 58f8bf8..9388d1c --- a/src/memory/alloc.h +++ b/src/memory/alloc.h @@ -12,13 +12,14 @@ #include "platform/detail.h" +#include "log.h" + namespace ipc { namespace mem { class static_alloc { public: static void swap(static_alloc&) {} - static void clear() {} static void* alloc(std::size_t size) { return size ? std::malloc(size) : nullptr; @@ -104,16 +105,11 @@ private: public: scope_alloc() = default; - scope_alloc(scope_alloc&& rhs) { swap(rhs); } + scope_alloc(scope_alloc && rhs) { swap(rhs); } scope_alloc& operator=(scope_alloc rhs) { swap(rhs); return (*this); } ~scope_alloc() { free_all(); } - template - void set_allocator(A && alc) { - alloc_ = std::forward(alc); - } - void swap(scope_alloc& rhs) { alloc_.swap(rhs.alloc_); base_t::swap(rhs); @@ -130,12 +126,6 @@ public: base_t::take(std::move(rhs)); } - void clear() { - free_all(); - tail_ = nullptr; - alloc_.~alloc_policy(); - } - void* alloc(std::size_t size) { auto curr = static_cast(alloc_.alloc(size += aligned_block_size)); curr->next_ = head_; @@ -156,10 +146,12 @@ namespace detail { class fixed_alloc_base { protected: + std::size_t block_size_; std::size_t init_expand_; void * cursor_; - void init(std::size_t init_expand) { + void init(std::size_t block_size, std::size_t init_expand) { + block_size_ = block_size; init_expand_ = init_expand; cursor_ = nullptr; } @@ -173,7 +165,12 @@ protected: } public: + void set_block_size(std::size_t block_size) { + block_size_ = block_size; + } + void swap(fixed_alloc_base& rhs) { + std::swap(block_size_ , rhs.block_size_); std::swap(init_expand_, rhs.init_expand_); std::swap(cursor_ , rhs.cursor_); } @@ -211,6 +208,63 @@ public: } }; +template +class fixed_alloc : public detail::fixed_alloc_base { +public: + using base_t = detail::fixed_alloc_base; + using alloc_policy = AllocP; + +private: + alloc_policy alloc_; + + void* try_expand() { + if (empty()) { + auto size = ExpandP::next(block_size_, init_expand_); + auto p = node_p(cursor_ = alloc_.alloc(size)); + for (std::size_t i = 0; i < (size / block_size_) - 1; ++i) + p = node_p((*p) = reinterpret_cast(p) + block_size_); + (*p) = nullptr; + } + return cursor_; + } + +public: + explicit fixed_alloc(std::size_t block_size, std::size_t init_expand = 1) { + init(block_size, init_expand); + } + + fixed_alloc(fixed_alloc && rhs) { + init(0, 0); + swap(rhs); + } + + fixed_alloc& operator=(fixed_alloc rhs) { + swap(rhs); + return (*this); + } + + void swap(fixed_alloc& rhs) { + alloc_.swap(rhs.alloc_); + base_t::swap(rhs); + } + + template + auto take(fixed_alloc && rhs) -> ipc::require::value> { + base_t::take(std::move(rhs)); + alloc_.take(std::move(rhs.alloc_)); + } + + void* alloc() { + void* p = try_expand(); + cursor_ = next(p); + return p; + } + + void* alloc(std::size_t) { + return alloc(); + } +}; + } // namespace detail struct fixed_expand_policy { @@ -227,9 +281,8 @@ struct fixed_expand_policy { return e * 2; } - template - static std::size_t next(std::size_t & e) { - auto n = ipc::detail::max(BlockSize, base_size) * e; + static std::size_t next(std::size_t block_size, std::size_t & e) { + auto n = ipc::detail::max(block_size, base_size) * e; e = next(e); return n; } @@ -238,73 +291,31 @@ struct fixed_expand_policy { template , typename ExpandP = fixed_expand_policy> -class fixed_alloc : public detail::fixed_alloc_base { +class fixed_alloc : public detail::fixed_alloc { public: - using base_t = detail::fixed_alloc_base; - using alloc_policy = AllocP; + using base_t = detail::fixed_alloc; enum : std::size_t { block_size = (ipc::detail::max)(BlockSize, sizeof(void*)) }; -private: - alloc_policy alloc_; - - void* try_expand() { - if (empty()) { - auto size = ExpandP::template next(init_expand_); - auto p = node_p(cursor_ = alloc_.alloc(size)); - for (std::size_t i = 0; i < (size / block_size) - 1; ++i) - p = node_p((*p) = reinterpret_cast(p) + block_size); - (*p) = nullptr; - } - return cursor_; - } - public: - explicit fixed_alloc(std::size_t init_expand = 1) { - init(init_expand); + explicit fixed_alloc(std::size_t init_expand = 1) + : base_t(block_size) { } - fixed_alloc(fixed_alloc&& rhs) : fixed_alloc() { swap(rhs); } - fixed_alloc& operator=(fixed_alloc rhs) { swap(rhs); return (*this); } + fixed_alloc(fixed_alloc && rhs) + : base_t(std::move(rhs)) { + } - template - void set_allocator(A && alc) { - alloc_ = std::forward(alc); + fixed_alloc& operator=(fixed_alloc rhs) { + swap(rhs); + return (*this); } void swap(fixed_alloc& rhs) { - alloc_.swap(rhs.alloc_); base_t::swap(rhs); } - - template - auto take(fixed_alloc && rhs) -> ipc::require::value> { - base_t::take(std::move(rhs)); - alloc_.take(std::move(rhs.alloc_)); - } - - template - auto take(fixed_alloc && rhs) -> ipc::require::value> { - base_t::take(std::move(rhs)); - } - - void clear() { - init_expand_ = ExpandP::prev(init_expand_); - cursor_ = nullptr; - alloc_.~alloc_policy(); - } - - void* alloc() { - void* p = try_expand(); - cursor_ = next(p); - return p; - } - - void* alloc(std::size_t) { - return alloc(); - } }; //////////////////////////////////////////////////////////////// @@ -374,14 +385,9 @@ private: public: variable_alloc() = default; - variable_alloc(variable_alloc&& rhs) { swap(rhs); } + variable_alloc(variable_alloc && rhs) { swap(rhs); } variable_alloc& operator=(variable_alloc rhs) { swap(rhs); return (*this); } - template - void set_allocator(A && alc) { - alloc_ = std::forward(alc); - } - void swap(variable_alloc& rhs) { alloc_.swap(rhs.alloc_); base_t::swap(rhs); @@ -398,10 +404,6 @@ public: base_t::take(std::move(rhs)); } - void clear() { - alloc_.~alloc_policy(); - } - void* alloc(std::size_t size) { if (size >= ChunkSize) { return alloc_.alloc(size); diff --git a/src/memory/resource.h b/src/memory/resource.h old mode 100644 new mode 100755 index 16ab19c..ca04a26 --- a/src/memory/resource.h +++ b/src/memory/resource.h @@ -21,19 +21,9 @@ using chunk_variable_alloc = static_wrapper>>; -template -using static_async_fixed = - static_wrapper>>; - -using big_size_alloc = variable_wrapper::block_size(default_mapping_policy<>::classes_size), - default_mapping_policy<>::iter_size * 2 >>; - -using async_pool_alloc = variable_wrapper, - big_size_alloc>; +using async_pool_alloc = + static_variable_wrapper>>; template using allocator = allocator_wrapper; diff --git a/src/memory/wrapper.h b/src/memory/wrapper.h old mode 100644 new mode 100755 index 1e525c8..4ed6fbc --- a/src/memory/wrapper.h +++ b/src/memory/wrapper.h @@ -1,14 +1,15 @@ #pragma once #include -#include +#include // ::new #include #include #include -#include -#include +#include // std::function +#include // std::forward #include -#include +#include // assert +#include // std::aligned_storage_t #include "def.h" #include "rw_lock.h" @@ -80,27 +81,27 @@ public: struct rebind { typedef allocator_wrapper other; }; constexpr size_type max_size(void) const noexcept { - return (std::numeric_limits::max)() / sizeof(T); + return (std::numeric_limits::max)() / sizeof(value_type); } public: pointer allocate(size_type count) noexcept { if (count == 0) return nullptr; if (count > this->max_size()) return nullptr; - return static_cast(alloc_.alloc(count * sizeof(T))); + return static_cast(alloc_.alloc(count * sizeof(value_type))); } void deallocate(pointer p, size_type count) noexcept { - alloc_.free(p, count * sizeof(T)); + alloc_.free(p, count * sizeof(value_type)); } template - static void construct(pointer p, P&&... params) { - ::new (static_cast(p)) T(std::forward

(params)...); + static void construct(pointer p, P && ... params) { + ::new (static_cast(p)) value_type(std::forward

(params) ...); } static void destroy(pointer p) { - p->~T(); + p->~value_type(); } }; @@ -148,11 +149,6 @@ public: master_allocs_.swap(rhs.master_allocs_); } - void clear() { - IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_); - master_allocs_.clear(); - } - void try_recover(alloc_policy & alc) { IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_); if (!master_allocs_.empty()) { @@ -174,18 +170,16 @@ public: template auto try_replenish(alloc_policy & alc, std::size_t /*size*/) - -> ipc::require::value && !has_remain::value && has_empty::value> { + -> ipc::require<(!detail::has_take::value || !has_remain::value) && has_empty::value> { if (!alc.empty()) return; - IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_); - if (!master_allocs_.empty()) { - alc.take(std::move(master_allocs_.back())); - master_allocs_.pop_back(); - } + try_recover(alc); } template constexpr auto try_replenish(alloc_policy & /*alc*/, std::size_t /*size*/) const noexcept - -> ipc::require::value || (!has_remain::value && !has_empty::value)> {} + -> ipc::require<(!detail::has_take::value || !has_remain::value) && !has_empty::value> { + // Do Nothing. + } void collect(alloc_policy && alc) { IPC_UNUSED_ auto guard = ipc::detail::unique_lock(master_lock_); @@ -199,7 +193,6 @@ public: using alloc_policy = AllocP; constexpr static void swap(empty_alloc_recycler&) noexcept {} - constexpr static void clear() noexcept {} constexpr static void try_recover(alloc_policy&) noexcept {} constexpr static auto try_replenish(alloc_policy&, std::size_t) noexcept {} constexpr static void collect(alloc_policy&&) noexcept {} @@ -218,51 +211,47 @@ private: async_wrapper * w_ = nullptr; public: - alloc_proxy(alloc_proxy && rhs) - : AllocP(std::move(rhs)) - {} + alloc_proxy(alloc_proxy && rhs) = default; - alloc_proxy(async_wrapper* w) - : AllocP(), w_(w) { - if (w_ == nullptr) return; + template + alloc_proxy(async_wrapper* w, P && ... pars) + : AllocP(std::forward

(pars) ...), w_(w) { + assert(w_ != nullptr); w_->recycler_.try_recover(*this); } ~alloc_proxy() { - if (w_ == nullptr) return; w_->recycler_.collect(std::move(*this)); } - auto alloc(std::size_t size) { - if (w_ != nullptr) { - w_->recycler_.try_replenish(*this, size); - } - return AllocP::alloc(size); - } + // auto alloc(std::size_t size) { + // w_->recycler_.try_replenish(*this, size); + // return AllocP::alloc(size); + // } }; friend class alloc_proxy; - auto& get_alloc() { - static tls::pointer tls_alc; - return *tls_alc.create(this); - } + using ref_t = alloc_proxy&; + using tls_t = tls::pointer; + + tls_t tls_; + std::function get_alloc_; public: - void swap(async_wrapper& rhs) { - recycler_.swap(rhs.recycler_); - } - - void clear() { - recycler_.clear(); + template + async_wrapper(P ... pars) { + get_alloc_ = [this, pars ...]()->ref_t { + return *tls_.create(this, pars ...); + }; } void* alloc(std::size_t size) { - return get_alloc().alloc(size); + return get_alloc_().alloc(size); } void free(void* p, std::size_t size) { - get_alloc().free(p, size); + get_alloc_().free(p, size); } }; @@ -281,16 +270,16 @@ private: alloc_policy alloc_; public: + template + sync_wrapper(P && ... pars) + : alloc_(std::forward

(pars) ...) + {} + void swap(sync_wrapper& rhs) { IPC_UNUSED_ auto guard = ipc::detail::unique_lock(lock_); alloc_.swap(rhs.alloc_); } - void clear() { - IPC_UNUSED_ auto guard = ipc::detail::unique_lock(lock_); - alloc_.~alloc_policy(); - } - void* alloc(std::size_t size) { IPC_UNUSED_ auto guard = ipc::detail::unique_lock(lock_); return alloc_.alloc(size); @@ -318,10 +307,6 @@ public: static void swap(static_wrapper&) {} - static void clear() { - instance().clear(); - } - static void* alloc(std::size_t size) { return instance().alloc(size); } @@ -341,62 +326,56 @@ struct default_mapping_policy { enum : std::size_t { base_size = BaseSize, iter_size = IterSize, - classes_size = 32 + classes_size = 64 }; - static const std::size_t table[classes_size]; - - IPC_CONSTEXPR_ static std::size_t classify(std::size_t size) noexcept { - auto index = (size <= base_size) ? 0 : ((size - base_size - 1) / iter_size); - return (index < classes_size) ? - // always uses default_mapping_policy<>::table - default_mapping_policy<>::table[index] : classes_size; + template + IPC_CONSTEXPR_ static void foreach(F f, P ... params) { + for (std::size_t i = 0; i < classes_size; ++i) f(i, params...); } - constexpr static std::size_t block_size(std::size_t value) noexcept { - return base_size + (value + 1) * iter_size; + IPC_CONSTEXPR_ static std::size_t block_size(std::size_t id) noexcept { + return (id < classes_size) ? (base_size + (id + 1) * iter_size) : 0; + } + + template + IPC_CONSTEXPR_ static auto classify(F f, D d, std::size_t size, P ... params) { + std::size_t id = (size - base_size - 1) / iter_size; + return (id < classes_size) ? f(id, params..., size) : d(params..., size); } }; -template -const std::size_t default_mapping_policy::table[default_mapping_policy::classes_size] = { - /* 1 - 8 ~ 32 */ - 0 , 1 , 2 , 3 , - /* 2 - 48 ~ 256 */ - 5 , 5 , 7 , 7 , 9 , 9 , 11, 11, 13, 13, 15, 15, 17, 17, - 19, 19, 21, 21, 23, 23, 25, 25, 27, 27, 29, 29, 31, 31 -}; - -template