From a4a7b85f472aea5b35ad7dc4221c378fc69bb03a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Fri, 7 May 2021 15:35:10 +0800 Subject: [PATCH 1/5] static_alloc is used by default --- src/libipc/memory/resource.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libipc/memory/resource.h b/src/libipc/memory/resource.h index e08d367..1084e64 100755 --- a/src/libipc/memory/resource.h +++ b/src/libipc/memory/resource.h @@ -17,12 +17,13 @@ namespace ipc { namespace mem { -using async_pool_alloc = static_wrapper, - fixed_expand_policy - >, - default_recycler >>>; +//using async_pool_alloc = static_wrapper, +// fixed_expand_policy +// >, +// default_recycler >>>; +using async_pool_alloc = ipc::mem::static_alloc; template using allocator = allocator_wrapper; From d6ab58fc6f97e43770219d60f833c998dcb0160d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Fri, 7 May 2021 15:41:32 +0800 Subject: [PATCH 2/5] add make_align for size alignment --- src/libipc/utility/utility.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libipc/utility/utility.h b/src/libipc/utility/utility.h index 4568d95..59d4ad1 100755 --- a/src/libipc/utility/utility.h +++ b/src/libipc/utility/utility.h @@ -53,4 +53,9 @@ T horrible_cast(U val) { return u.out; } +IPC_CONSTEXPR_ std::size_t make_align(std::size_t align, std::size_t size) { + // align must be 2^n + return (size + align - 1) & ~(align - 1); +} + } // namespace ipc From 681f8e6736ab257a6b48e4b6aa3f452d8748b693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Fri, 7 May 2021 15:48:31 +0800 Subject: [PATCH 3/5] add large_msg_align for cache memory alignment --- include/libipc/def.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/libipc/def.h b/include/libipc/def.h index d9cfdc0..9be5206 100755 --- a/include/libipc/def.h +++ b/include/libipc/def.h @@ -29,6 +29,7 @@ enum : std::size_t { invalid_value = (std::numeric_limits::max)(), data_length = 64, large_msg_limit = data_length, + large_msg_align = 512, large_msg_cache = 32, default_timeout = 100 // ms }; From 9aab0d4f2107058e87d120c38e8cbe03f966602c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Fri, 7 May 2021 16:03:33 +0800 Subject: [PATCH 4/5] Update ipc.cpp Optimizes the number of handles to the large message cache. --- src/ipc.cpp | 155 +++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 82 deletions(-) diff --git a/src/ipc.cpp b/src/ipc.cpp index 6731ba5..869eb7f 100755 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -21,6 +21,7 @@ #include "libipc/utility/log.h" #include "libipc/utility/id_pool.h" +#include "libipc/utility/utility.h" #include "libipc/memory/resource.h" @@ -90,77 +91,68 @@ auto cc_acc() { return static_cast(acc_h.get()); } -auto& cls_storages() { - struct cls_t { - ipc::shm::handle id_info_; - std::array::max_count> mems_; - }; - static ipc::unordered_map cls_s; - return cls_s; -} - -auto& cls_lock() { - static ipc::spin_lock cls_l; - return cls_l; -} - -struct cls_info_t { +struct chunk_info_t { ipc::id_pool<> pool_; ipc::spin_lock lock_; + + IPC_CONSTEXPR_ static std::size_t chunks_elem_size(std::size_t chunk_size) noexcept { + return ipc::make_align(alignof(std::max_align_t), chunk_size + sizeof(acc_t)); + } + + IPC_CONSTEXPR_ static std::size_t chunks_mem_size(std::size_t chunk_size) noexcept { + return ipc::id_pool<>::max_count * chunks_elem_size(chunk_size); + } + + ipc::byte_t *at(std::size_t chunk_size, std::size_t id) noexcept { + return reinterpret_cast(this + 1) + (chunks_elem_size(chunk_size) * id); + } }; -constexpr std::size_t calc_cls_size(std::size_t size) noexcept { - return (((size - 1) / ipc::large_msg_limit) + 1) * ipc::large_msg_limit; +auto& chunk_storages() { + class chunk_t { + ipc::shm::handle handle_; + + public: + chunk_info_t *get_info(std::size_t chunk_size) { + if (!handle_.valid() && + !handle_.acquire( ("__CHUNK_INFO__" + ipc::to_string(chunk_size)).c_str(), + sizeof(chunk_info_t) + chunk_info_t::chunks_mem_size(chunk_size) )) { + ipc::error("[chunk_storages] chunk_shm.id_info_.acquire failed: chunk_size = %zd\n", chunk_size); + return nullptr; + } + auto info = static_cast(handle_.get()); + if (info == nullptr) { + ipc::error("[chunk_storages] chunk_shm.id_info_.get failed: chunk_size = %zd\n", chunk_size); + return nullptr; + } + return info; + } + }; + static ipc::unordered_map chunk_s; + return chunk_s; } -auto& cls_storage(std::size_t cls_size) { - IPC_UNUSED_ auto guard = ipc::detail::unique_lock(cls_lock()); - return cls_storages()[cls_size]; +auto& chunk_lock() { + static ipc::spin_lock chunk_l; + return chunk_l; } -template -cls_info_t* cls_storage_info(const char* func, T& cls_shm, std::size_t cls_size) { - if (!cls_shm.id_info_.valid() && - !cls_shm.id_info_.acquire(("__CLS_INFO__" + ipc::to_string(cls_size)).c_str(), sizeof(cls_info_t))) { - ipc::error("[%s] cls_shm.id_info_.acquire failed: cls_size = %zd\n", func, cls_size); - return nullptr; - } - auto info = static_cast(cls_shm.id_info_.get()); - if (info == nullptr) { - ipc::error("[%s] cls_shm.id_info_.get failed: cls_size = %zd\n", func, cls_size); - return nullptr; - } - return info; +constexpr std::size_t calc_chunk_size(std::size_t size) noexcept { + return ( ((size - 1) / ipc::large_msg_align) + 1 ) * ipc::large_msg_align; } -template -ipc::byte_t* cls_storage_mem(const char* func, T& cls_shm, std::size_t cls_size, std::size_t id) { - if (id == ipc::invalid_value) { - return nullptr; - } - if (!cls_shm.mems_[id].valid() && - !cls_shm.mems_[id].acquire(("__CLS_MEM_BLOCK__" + ipc::to_string(cls_size) + - "__" + ipc::to_string(id)).c_str(), - cls_size + sizeof(acc_t))) { - ipc::error("[%s] cls_shm.mems_[id].acquire failed: id = %zd, cls_size = %zd\n", func, id, cls_size); - return nullptr; - } - - auto ptr = static_cast(cls_shm.mems_[id].get()); - if (ptr == nullptr) { - ipc::error("[%s] cls_shm.mems_[id].get failed: id = %zd, cls_size = %zd\n", func, id, cls_size); - return nullptr; - } - return ptr; +auto& chunk_storage(std::size_t chunk_size) { + IPC_UNUSED_ auto guard = ipc::detail::unique_lock(chunk_lock()); + return chunk_storages()[chunk_size]; } std::pair apply_storage(std::size_t conn_count, std::size_t size) { if (conn_count == 0) return {}; - std::size_t cls_size = calc_cls_size(size); - auto & cls_shm = cls_storage(cls_size); + std::size_t chunk_size = calc_chunk_size(size); + auto & chunk_shm = chunk_storage(chunk_size); - auto info = cls_storage_info("apply_storage", cls_shm, cls_size); + auto info = chunk_shm.get_info(chunk_size); if (info == nullptr) return {}; info->lock_.lock(); @@ -169,20 +161,23 @@ std::pair apply_storage(std::size_t conn_count, std::size_t auto id = info->pool_.acquire(); info->lock_.unlock(); - auto ptr = cls_storage_mem("apply_storage", cls_shm, cls_size, id); + auto ptr = info->at(chunk_size, id); if (ptr == nullptr) return {}; - reinterpret_cast(ptr + cls_size)->store(static_cast(conn_count), std::memory_order_release); + reinterpret_cast(ptr + chunk_size)->store(static_cast(conn_count), std::memory_order_release); return { id, ptr }; } -void* find_storage(std::size_t id, std::size_t size) { - std::size_t cls_size = calc_cls_size(size); - auto & cls_shm = cls_storage(cls_size); +void *find_storage(std::size_t id, std::size_t size) { + std::size_t chunk_size = calc_chunk_size(size); + auto & chunk_shm = chunk_storage(chunk_size); - auto ptr = cls_storage_mem("find_storage", cls_shm, cls_size, id); + auto info = chunk_shm.get_info(chunk_size); + if (info == nullptr) return nullptr; + + auto ptr = info->at(chunk_size, id); if (ptr == nullptr) return nullptr; - if (reinterpret_cast(ptr + cls_size)->load(std::memory_order_acquire) == 0) { - ipc::error("[find_storage] cc test failed: id = %zd, cls_size = %zd\n", id, cls_size); + if (reinterpret_cast(ptr + chunk_size)->load(std::memory_order_acquire) == 0) { + ipc::error("[find_storage] cc test failed: id = %zd, chunk_size = %zd\n", id, chunk_size); return nullptr; } return ptr; @@ -194,26 +189,22 @@ void recycle_storage(std::size_t id, std::size_t size) { return; } - std::size_t cls_size = calc_cls_size(size); - auto & cls_shm = cls_storage(cls_size); + std::size_t chunk_size = calc_chunk_size(size); + auto & chunk_shm = chunk_storage(chunk_size); - if (!cls_shm.mems_[id].valid()) { - ipc::error("[recycle_storage] should find storage first: id = %zd, cls_size = %zd\n", id, cls_size); - return; - } - auto ptr = static_cast(cls_shm.mems_[id].get()); + auto info = chunk_shm.get_info(chunk_size); + if (info == nullptr) return; + + auto ptr = info->at(chunk_size, id); if (ptr == nullptr) { - ipc::error("[recycle_storage] cls_shm.mems_[id].get failed: id = %zd, cls_size = %zd\n", id, cls_size); + ipc::error("[recycle_storage] chunk_shm.mems[%zd] failed: chunk_size = %zd\n", id, chunk_size); return; } - if (reinterpret_cast(ptr + cls_size)->fetch_sub(1, std::memory_order_acq_rel) > 1) { + if (reinterpret_cast(ptr + chunk_size)->fetch_sub(1, std::memory_order_acq_rel) > 1) { // not the last receiver, just return return; } - auto info = cls_storage_info("recycle_storage", cls_shm, cls_size); - if (info == nullptr) return; - info->lock_.lock(); info->pool_.release(id); info->lock_.unlock(); @@ -225,13 +216,16 @@ void clear_storage(std::size_t id, std::size_t size) { return; } - std::size_t cls_size = calc_cls_size(size); - auto & cls_shm = cls_storage(cls_size); + std::size_t chunk_size = calc_chunk_size(size); + auto & chunk_shm = chunk_storage(chunk_size); - auto ptr = cls_storage_mem("clear_storage", cls_shm, cls_size, id); + auto info = chunk_shm.get_info(chunk_size); + if (info == nullptr) return; + + auto ptr = info->at(chunk_size, id); if (ptr == nullptr) return; - auto cc_flag = reinterpret_cast(ptr + cls_size); + auto cc_flag = reinterpret_cast(ptr + chunk_size); for (unsigned k = 0;;) { auto cc_curr = cc_flag->load(std::memory_order_acquire); if (cc_curr == 0) return; // means this id has been cleared @@ -241,9 +235,6 @@ void clear_storage(std::size_t id, std::size_t size) { ipc::yield(k); } - auto info = cls_storage_info("clear_storage", cls_shm, cls_size); - if (info == nullptr) return; - info->lock_.lock(); info->pool_.release(id); info->lock_.unlock(); From a85199d2d4034ac7f77ad67d60ee42e168ba5a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Fri, 7 May 2021 16:47:49 +0800 Subject: [PATCH 5/5] Update ipc.cpp fix bug: id == invalid_value not processed. --- src/ipc.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ipc.cpp b/src/ipc.cpp index 869eb7f..12a629b 100755 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -104,6 +104,7 @@ struct chunk_info_t { } ipc::byte_t *at(std::size_t chunk_size, std::size_t id) noexcept { + if (id == ipc::invalid_value) return nullptr; return reinterpret_cast(this + 1) + (chunks_elem_size(chunk_size) * id); } }; @@ -168,6 +169,11 @@ std::pair apply_storage(std::size_t conn_count, std::size_t } void *find_storage(std::size_t id, std::size_t size) { + if (id == ipc::invalid_value) { + ipc::error("[find_storage] id is invalid: id = %zd, size = %zd\n", id, size); + return nullptr; + } + std::size_t chunk_size = calc_chunk_size(size); auto & chunk_shm = chunk_storage(chunk_size);