Skip to content

Commit 9aab0d4

Browse files
authored
Update ipc.cpp
Optimizes the number of handles to the large message cache.
1 parent 681f8e6 commit 9aab0d4

File tree

1 file changed

+73
-82
lines changed

1 file changed

+73
-82
lines changed

src/ipc.cpp

Lines changed: 73 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "libipc/utility/log.h"
2323
#include "libipc/utility/id_pool.h"
24+
#include "libipc/utility/utility.h"
2425

2526
#include "libipc/memory/resource.h"
2627

@@ -90,77 +91,68 @@ auto cc_acc() {
9091
return static_cast<acc_t*>(acc_h.get());
9192
}
9293

93-
auto& cls_storages() {
94-
struct cls_t {
95-
ipc::shm::handle id_info_;
96-
std::array<ipc::shm::handle, ipc::id_pool<>::max_count> mems_;
97-
};
98-
static ipc::unordered_map<std::size_t, cls_t> cls_s;
99-
return cls_s;
100-
}
101-
102-
auto& cls_lock() {
103-
static ipc::spin_lock cls_l;
104-
return cls_l;
105-
}
106-
107-
struct cls_info_t {
94+
struct chunk_info_t {
10895
ipc::id_pool<> pool_;
10996
ipc::spin_lock lock_;
97+
98+
IPC_CONSTEXPR_ static std::size_t chunks_elem_size(std::size_t chunk_size) noexcept {
99+
return ipc::make_align(alignof(std::max_align_t), chunk_size + sizeof(acc_t));
100+
}
101+
102+
IPC_CONSTEXPR_ static std::size_t chunks_mem_size(std::size_t chunk_size) noexcept {
103+
return ipc::id_pool<>::max_count * chunks_elem_size(chunk_size);
104+
}
105+
106+
ipc::byte_t *at(std::size_t chunk_size, std::size_t id) noexcept {
107+
return reinterpret_cast<ipc::byte_t *>(this + 1) + (chunks_elem_size(chunk_size) * id);
108+
}
110109
};
111110

112-
constexpr std::size_t calc_cls_size(std::size_t size) noexcept {
113-
return (((size - 1) / ipc::large_msg_limit) + 1) * ipc::large_msg_limit;
111+
auto& chunk_storages() {
112+
class chunk_t {
113+
ipc::shm::handle handle_;
114+
115+
public:
116+
chunk_info_t *get_info(std::size_t chunk_size) {
117+
if (!handle_.valid() &&
118+
!handle_.acquire( ("__CHUNK_INFO__" + ipc::to_string(chunk_size)).c_str(),
119+
sizeof(chunk_info_t) + chunk_info_t::chunks_mem_size(chunk_size) )) {
120+
ipc::error("[chunk_storages] chunk_shm.id_info_.acquire failed: chunk_size = %zd\n", chunk_size);
121+
return nullptr;
122+
}
123+
auto info = static_cast<chunk_info_t*>(handle_.get());
124+
if (info == nullptr) {
125+
ipc::error("[chunk_storages] chunk_shm.id_info_.get failed: chunk_size = %zd\n", chunk_size);
126+
return nullptr;
127+
}
128+
return info;
129+
}
130+
};
131+
static ipc::unordered_map<std::size_t, chunk_t> chunk_s;
132+
return chunk_s;
114133
}
115134

116-
auto& cls_storage(std::size_t cls_size) {
117-
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(cls_lock());
118-
return cls_storages()[cls_size];
135+
auto& chunk_lock() {
136+
static ipc::spin_lock chunk_l;
137+
return chunk_l;
119138
}
120139

121-
template <typename T>
122-
cls_info_t* cls_storage_info(const char* func, T& cls_shm, std::size_t cls_size) {
123-
if (!cls_shm.id_info_.valid() &&
124-
!cls_shm.id_info_.acquire(("__CLS_INFO__" + ipc::to_string(cls_size)).c_str(), sizeof(cls_info_t))) {
125-
ipc::error("[%s] cls_shm.id_info_.acquire failed: cls_size = %zd\n", func, cls_size);
126-
return nullptr;
127-
}
128-
auto info = static_cast<cls_info_t*>(cls_shm.id_info_.get());
129-
if (info == nullptr) {
130-
ipc::error("[%s] cls_shm.id_info_.get failed: cls_size = %zd\n", func, cls_size);
131-
return nullptr;
132-
}
133-
return info;
140+
constexpr std::size_t calc_chunk_size(std::size_t size) noexcept {
141+
return ( ((size - 1) / ipc::large_msg_align) + 1 ) * ipc::large_msg_align;
134142
}
135143

136-
template <typename T>
137-
ipc::byte_t* cls_storage_mem(const char* func, T& cls_shm, std::size_t cls_size, std::size_t id) {
138-
if (id == ipc::invalid_value) {
139-
return nullptr;
140-
}
141-
if (!cls_shm.mems_[id].valid() &&
142-
!cls_shm.mems_[id].acquire(("__CLS_MEM_BLOCK__" + ipc::to_string(cls_size) +
143-
"__" + ipc::to_string(id)).c_str(),
144-
cls_size + sizeof(acc_t))) {
145-
ipc::error("[%s] cls_shm.mems_[id].acquire failed: id = %zd, cls_size = %zd\n", func, id, cls_size);
146-
return nullptr;
147-
}
148-
149-
auto ptr = static_cast<ipc::byte_t *>(cls_shm.mems_[id].get());
150-
if (ptr == nullptr) {
151-
ipc::error("[%s] cls_shm.mems_[id].get failed: id = %zd, cls_size = %zd\n", func, id, cls_size);
152-
return nullptr;
153-
}
154-
return ptr;
144+
auto& chunk_storage(std::size_t chunk_size) {
145+
IPC_UNUSED_ auto guard = ipc::detail::unique_lock(chunk_lock());
146+
return chunk_storages()[chunk_size];
155147
}
156148

157149
std::pair<std::size_t, void*> apply_storage(std::size_t conn_count, std::size_t size) {
158150
if (conn_count == 0) return {};
159151

160-
std::size_t cls_size = calc_cls_size(size);
161-
auto & cls_shm = cls_storage(cls_size);
152+
std::size_t chunk_size = calc_chunk_size(size);
153+
auto & chunk_shm = chunk_storage(chunk_size);
162154

163-
auto info = cls_storage_info("apply_storage", cls_shm, cls_size);
155+
auto info = chunk_shm.get_info(chunk_size);
164156
if (info == nullptr) return {};
165157

166158
info->lock_.lock();
@@ -169,20 +161,23 @@ std::pair<std::size_t, void*> apply_storage(std::size_t conn_count, std::size_t
169161
auto id = info->pool_.acquire();
170162
info->lock_.unlock();
171163

172-
auto ptr = cls_storage_mem("apply_storage", cls_shm, cls_size, id);
164+
auto ptr = info->at(chunk_size, id);
173165
if (ptr == nullptr) return {};
174-
reinterpret_cast<acc_t*>(ptr + cls_size)->store(static_cast<msg_id_t>(conn_count), std::memory_order_release);
166+
reinterpret_cast<acc_t*>(ptr + chunk_size)->store(static_cast<msg_id_t>(conn_count), std::memory_order_release);
175167
return { id, ptr };
176168
}
177169

178-
void* find_storage(std::size_t id, std::size_t size) {
179-
std::size_t cls_size = calc_cls_size(size);
180-
auto & cls_shm = cls_storage(cls_size);
170+
void *find_storage(std::size_t id, std::size_t size) {
171+
std::size_t chunk_size = calc_chunk_size(size);
172+
auto & chunk_shm = chunk_storage(chunk_size);
173+
174+
auto info = chunk_shm.get_info(chunk_size);
175+
if (info == nullptr) return nullptr;
181176

182-
auto ptr = cls_storage_mem("find_storage", cls_shm, cls_size, id);
177+
auto ptr = info->at(chunk_size, id);
183178
if (ptr == nullptr) return nullptr;
184-
if (reinterpret_cast<acc_t*>(ptr + cls_size)->load(std::memory_order_acquire) == 0) {
185-
ipc::error("[find_storage] cc test failed: id = %zd, cls_size = %zd\n", id, cls_size);
179+
if (reinterpret_cast<acc_t*>(ptr + chunk_size)->load(std::memory_order_acquire) == 0) {
180+
ipc::error("[find_storage] cc test failed: id = %zd, chunk_size = %zd\n", id, chunk_size);
186181
return nullptr;
187182
}
188183
return ptr;
@@ -194,26 +189,22 @@ void recycle_storage(std::size_t id, std::size_t size) {
194189
return;
195190
}
196191

197-
std::size_t cls_size = calc_cls_size(size);
198-
auto & cls_shm = cls_storage(cls_size);
192+
std::size_t chunk_size = calc_chunk_size(size);
193+
auto & chunk_shm = chunk_storage(chunk_size);
199194

200-
if (!cls_shm.mems_[id].valid()) {
201-
ipc::error("[recycle_storage] should find storage first: id = %zd, cls_size = %zd\n", id, cls_size);
202-
return;
203-
}
204-
auto ptr = static_cast<ipc::byte_t*>(cls_shm.mems_[id].get());
195+
auto info = chunk_shm.get_info(chunk_size);
196+
if (info == nullptr) return;
197+
198+
auto ptr = info->at(chunk_size, id);
205199
if (ptr == nullptr) {
206-
ipc::error("[recycle_storage] cls_shm.mems_[id].get failed: id = %zd, cls_size = %zd\n", id, cls_size);
200+
ipc::error("[recycle_storage] chunk_shm.mems[%zd] failed: chunk_size = %zd\n", id, chunk_size);
207201
return;
208202
}
209-
if (reinterpret_cast<acc_t*>(ptr + cls_size)->fetch_sub(1, std::memory_order_acq_rel) > 1) {
203+
if (reinterpret_cast<acc_t*>(ptr + chunk_size)->fetch_sub(1, std::memory_order_acq_rel) > 1) {
210204
// not the last receiver, just return
211205
return;
212206
}
213207

214-
auto info = cls_storage_info("recycle_storage", cls_shm, cls_size);
215-
if (info == nullptr) return;
216-
217208
info->lock_.lock();
218209
info->pool_.release(id);
219210
info->lock_.unlock();
@@ -225,13 +216,16 @@ void clear_storage(std::size_t id, std::size_t size) {
225216
return;
226217
}
227218

228-
std::size_t cls_size = calc_cls_size(size);
229-
auto & cls_shm = cls_storage(cls_size);
219+
std::size_t chunk_size = calc_chunk_size(size);
220+
auto & chunk_shm = chunk_storage(chunk_size);
221+
222+
auto info = chunk_shm.get_info(chunk_size);
223+
if (info == nullptr) return;
230224

231-
auto ptr = cls_storage_mem("clear_storage", cls_shm, cls_size, id);
225+
auto ptr = info->at(chunk_size, id);
232226
if (ptr == nullptr) return;
233227

234-
auto cc_flag = reinterpret_cast<acc_t*>(ptr + cls_size);
228+
auto cc_flag = reinterpret_cast<acc_t*>(ptr + chunk_size);
235229
for (unsigned k = 0;;) {
236230
auto cc_curr = cc_flag->load(std::memory_order_acquire);
237231
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) {
241235
ipc::yield(k);
242236
}
243237

244-
auto info = cls_storage_info("clear_storage", cls_shm, cls_size);
245-
if (info == nullptr) return;
246-
247238
info->lock_.lock();
248239
info->pool_.release(id);
249240
info->lock_.unlock();

0 commit comments

Comments
 (0)