diff --git a/include/ipc.h b/include/ipc.h index 9829e19..6dbe7ec 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -20,7 +20,7 @@ buff_t make_buff(byte_t const (& data)[N]) { return make_buff(data, N); } IPC_EXPORT handle_t connect (char const * name); IPC_EXPORT void disconnect(handle_t h); -IPC_EXPORT std::size_t conn_count(handle_t h); +IPC_EXPORT std::size_t recv_count(handle_t h); IPC_EXPORT bool send(handle_t h, void const * data, std::size_t size); IPC_EXPORT buff_t recv(handle_t h); @@ -43,7 +43,8 @@ public: bool connect(char const * name); void disconnect(); - std::size_t conn_count() const; + + std::size_t recv_count() const; bool send(void const * data, std::size_t size); bool send(buff_t const & buff); diff --git a/src/ipc.cpp b/src/ipc.cpp index 932a879..1dc2962 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -13,7 +13,7 @@ #include "def.h" #include "circ_queue.h" #include "rw_lock.h" -#include "tls_pointer.h" +//#include "tls_pointer.h" namespace { @@ -36,13 +36,13 @@ struct shm_info_t { queue_t::array_t elems_; // the circ_elem_array in shm }; -/* - * thread_local stl object's destructor causing crash - * See: https://sourceforge.net/p/mingw-w64/bugs/527/ - * https://sourceforge.net/p/mingw-w64/bugs/727/ -*/ -/*thread_local*/ -tls::pointer> recv_caches__; +///* +// * thread_local stl object's destructor causing crash +// * See: https://sourceforge.net/p/mingw-w64/bugs/527/ +// * https://sourceforge.net/p/mingw-w64/bugs/727/ +//*/ +///*thread_local*/ +//tls::pointer> recv_caches__; std::unordered_map h2q__; rw_lock h2q_lc__; @@ -90,15 +90,9 @@ handle_t connect(char const * name) { if (mem == nullptr) { return nullptr; } - queue_t* queue; { std::unique_lock guard { h2q_lc__ }; - queue = &(h2q__[h]); - if (queue == nullptr) { - return nullptr; - } - queue->attach(&(static_cast(mem)->elems_)); - queue->connect(); + h2q__[h].attach(&(static_cast(mem)->elems_)); } h_guard.release(); return h; @@ -121,7 +115,7 @@ void disconnect(handle_t h) { shm::release(h, sizeof(queue_t)); } -std::size_t conn_count(handle_t h) { +std::size_t recv_count(handle_t h) { auto queue = queue_of(h); if (queue == nullptr) { return error_count; @@ -174,7 +168,7 @@ buff_t recv(handle_t h) { if (!queue->connected()) { queue->connect(); } - auto rcs = recv_caches__.create(); + thread_local std::unordered_map rcs; while(1) { // pop a new message auto msg = queue->pop(); @@ -182,13 +176,13 @@ buff_t recv(handle_t h) { std::size_t remain = static_cast( static_cast(data_length) + msg.remain_); // find cache with msg.id_ - auto cache_it = rcs->find(msg.id_); - if (cache_it == rcs->end()) { + auto cache_it = rcs.find(msg.id_); + if (cache_it == rcs.end()) { if (remain <= data_length) { return make_buff(msg.data_, remain); } // cache the first message fragment - else rcs->emplace(msg.id_, make_buff(msg.data_)); + else rcs.emplace(msg.id_, make_buff(msg.data_)); } // has cached before this message else { @@ -198,7 +192,7 @@ buff_t recv(handle_t h) { cache.insert(cache.end(), msg.data_, msg.data_ + remain); // finish this message, erase it from cache auto buf = std::move(cache); - rcs->erase(cache_it); + rcs.erase(cache_it); return buf; } // there are remain datas after this message @@ -263,8 +257,8 @@ void channel::disconnect() { ipc::disconnect(impl(p_)->h_); } -std::size_t channel::conn_count() const { - return ipc::conn_count(impl(p_)->h_); +std::size_t channel::recv_count() const { + return ipc::recv_count(impl(p_)->h_); } bool channel::send(void const *data, std::size_t size) { diff --git a/test/test.h b/test/test.h index 174b756..cdc7765 100644 --- a/test/test.h +++ b/test/test.h @@ -40,11 +40,11 @@ struct test_stopwatch { } }; -template +template struct test_verify; template <> -struct test_verify { +struct test_verify { test_verify (int) {} void prepare (void*) {} void push_data(int, ...) {} @@ -54,7 +54,7 @@ struct test_verify { template struct test_cq; -template +template void benchmark_prod_cons(T* cq) { test_cq tcq { cq }; diff --git a/test/test_circ.cpp b/test/test_circ.cpp index 9363e2c..3a0a7de 100644 --- a/test/test_circ.cpp +++ b/test/test_circ.cpp @@ -23,8 +23,8 @@ struct msg_t { } // internal-linkage -template -struct test_verify { +template <> +struct test_verify { std::unordered_map>* list_; int lcount_; @@ -212,7 +212,7 @@ void Unit::test_inst() { template void test_prod_cons() { - benchmark_prod_cons(cq__); + benchmark_prod_cons>(cq__); } void Unit::test_prod_cons_1v1() { diff --git a/test/test_ipc.cpp b/test/test_ipc.cpp index 92d88a4..289bbb8 100644 --- a/test/test_ipc.cpp +++ b/test/test_ipc.cpp @@ -17,11 +17,13 @@ # include // abi::__cxa_demangle #endif/*__GNUC__*/ -#include "ipc.h" -#include "rw_lock.h" #include "stopwatch.hpp" #include "spin_lock.hpp" #include "random.hpp" + +#include "ipc.h" +#include "rw_lock.h" + #include "test.h" namespace { @@ -29,8 +31,8 @@ namespace { std::vector datas__; constexpr int DataMin = 2; -constexpr int DataMax = 512; -constexpr int LoopCount = 100/*0*//*000*/; +constexpr int DataMax = 256; +constexpr int LoopCount = 100000; } // internal-linkage @@ -39,22 +41,24 @@ struct test_cq { using cn_t = ipc::channel; std::string conn_name_; - std::size_t conn_count_ = 0; test_cq(void*) - : conn_name_("test-ipc-channel") - {} - - cn_t connect() { - cn_t cn { conn_name_.c_str() }; - conn_count_ = cn.conn_count(); - return cn; + : conn_name_("test-ipc-channel") { + auto watcher = connect(); + QCOMPARE(watcher.recv_count(), 0); } - void disconnect(cn_t&) {} + cn_t connect() { + return { conn_name_.c_str() }; + } + + void disconnect(cn_t& cn) { + cn.disconnect(); + } void wait_start(int M) { - while (conn_count_ != static_cast(M)) { + auto watcher = connect(); + while (watcher.recv_count() != static_cast(M)) { std::this_thread::yield(); } } @@ -74,32 +78,32 @@ struct test_cq { if (n < 0) { cn.send(ipc::buff_t { '\0' }); } - else cn.send(datas__[n]); + else cn.send(datas__[static_cast(n)]); } }; -//template <> -//struct test_verify { -// std::unordered_map> list_; -// int lcount_; +template <> +struct test_verify { + std::unordered_map> list_; + int lcount_; -// test_verify(int M) : lcount_{ M } {} + test_verify(int M) : lcount_{ M } {} -// void prepare(void* pt) { -// std::cout << "start consumer: " << pt << std::endl; -// } + void prepare(void* pt) { + std::cout << "start consumer: " << pt << std::endl; + } -// void push_data(int cid, ipc::buff_t const & msg) { -// list_[cid].emplace_back(std::move(msg)); -// } + void push_data(int cid, ipc::buff_t const & msg) { + list_[cid].emplace_back(std::move(msg)); + } -// void verify(int /*N*/, int /*Loops*/) { -// std::cout << "verifying..." << std::endl; -// for (int m = 0; m < lcount_; ++m) { -// QCOMPARE(datas__, list_[m]); -// } -// } -//}; + void verify(int /*N*/, int /*Loops*/) { + std::cout << "verifying..." << std::endl; + for (int m = 0; m < lcount_; ++m) { + QCOMPARE(datas__, list_[m]); + } + } +}; namespace { @@ -201,7 +205,7 @@ void benchmark_lc() { sw.print_elapsed(W, R, Loops); } std::uint64_t sum = 0; - for (int i : seq) sum += i; + for (int i : seq) sum += static_cast(i); QCOMPARE(sum, acc(1, Loops) * std::extent::value); }); } @@ -230,10 +234,10 @@ void benchmark_lc() { } template -void test_performance() { +void test_lock_performance() { std::cout << std::endl - << "test_performance: [" << W << ":" << R << "]" + << "test_lock_performance: [" << W << ":" << R << "]" << std::endl; benchmark_lc(); @@ -243,10 +247,10 @@ void test_performance() { } void Unit::test_rw_lock() { - test_performance<1, 1>(); - test_performance<4, 4>(); - test_performance<1, 8>(); - test_performance<8, 1>(); + test_lock_performance<1, 1>(); + test_lock_performance<4, 4>(); + test_lock_performance<1, 8>(); + test_lock_performance<8, 1>(); } void Unit::test_send_recv() { @@ -340,8 +344,49 @@ void Unit::test_channel() { t2.join(); } +template +void test_prod_cons() { + benchmark_prod_cons>((ipc::channel*)nullptr); +} + +template +struct test_performance { + static void start() { + test_performance

::start(); + test_prod_cons(); + } +}; + +template +struct test_performance<1, C> { + static void start() { + test_performance<1, C - 1>::start(); + test_prod_cons<1, C, false>(); + } +}; + +template +struct test_performance { + static void start() { + test_performance

::start(); + test_prod_cons(); + } +}; + +template <> +struct test_performance<1, 1> { + static void start() { + test_prod_cons<1, 1, false>(); + } +}; + void Unit::test_channel_performance() { - benchmark_prod_cons<1, 1, LoopCount, false>((ipc::channel*)nullptr); + test_prod_cons<1, 1>(); + test_prod_cons<1, 8>(); + + test_performance<1 , 10>::start(); + test_performance<10, 1 >::start(); + test_performance<10, 10>::start(); } } // internal-linkage