mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
update performence data; add implementation of pool_alloc::clear
This commit is contained in:
parent
33017b80fc
commit
2e26176234
51
README.md
51
README.md
@ -13,49 +13,16 @@ A high-performance inter-process communication using shared memory on Linux/Wind
|
|||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||
| Environment | Value |
|
Environment | Value
|
||||||
| ------ | ------ |
|
------ | ------
|
||||||
| CPU | AMD Ryzen™ 5 1400 Quad-Core |
|
Device | Lenovo ThinkPad T450
|
||||||
| RAM | 32 GB |
|
CPU | Intel® Core™ i5-4300U @ 2.5 GHz
|
||||||
| OS | Windows 10 Pro for Education x64 |
|
RAM | 16 GB
|
||||||
| Compiler | MSVC 2017 15.9.4 x64 |
|
OS | Windows 7 Ultimate x64
|
||||||
|
Compiler | MSVC 2017 15.9.4
|
||||||
|
|
||||||
UT & benchmark test function, see: [test](test)
|
UT & benchmark test function: [test](test)
|
||||||
|
Performance data: [performence.xlsx](performence.xlsx)
|
||||||
### ipc::circ::queue
|
|
||||||
|
|
||||||
| PROD-CONS: 1-N | DATAS: 12bits * 1000000 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| `1-1` | `47.4050 ms, 0.047405 us/d` |
|
|
||||||
| `1-2` | `113.793 ms, 0.113793 us/d` |
|
|
||||||
| `1-4` | `319.196 ms, 0.319196 us/d` |
|
|
||||||
| `1-8` | `225.258 ms, 0.225258 us/d` |
|
|
||||||
|
|
||||||
### ipc::route
|
|
||||||
|
|
||||||
| PROD-CONS: 1-N | DATAS: Random 2-256bits * 100000 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| `RTT` | `103.280 ms, 1.03280 us/d` |
|
|
||||||
| `1-1` | `78.6670 ms, 0.78667 us/d` |
|
|
||||||
| `1-2` | `165.601 ms, 1.65601 us/d` |
|
|
||||||
| `1-4` | `223.183 ms, 2.23183 us/d` |
|
|
||||||
| `1-8` | `246.161 ms, 2.46161 us/d` |
|
|
||||||
|
|
||||||
### ipc::channel
|
|
||||||
|
|
||||||
| PROD-CONS: N-M | DATAS: Random 2-256bits * 100000 |
|
|
||||||
| ------ | ------ |
|
|
||||||
| `RTT` | `184.711 ms, 1.84711 us/d` |
|
|
||||||
| `1-1` | `122.186 ms, 1.22186 us/d` |
|
|
||||||
| `1-2` | `226.518 ms, 2.26518 us/d` |
|
|
||||||
| `1-4` | `369.239 ms, 3.69239 us/d` |
|
|
||||||
| `1-8` | `620.199 ms, 6.20199 us/d` |
|
|
||||||
| `2-1` | `287.960 ms, 1.43980 us/d` |
|
|
||||||
| `4-1` | `542.050 ms, 1.35512 us/d` |
|
|
||||||
| `8-1` | `1406.61 ms, 1.75826 us/d` |
|
|
||||||
| `2-2` | `475.095 ms, 2.37547 us/d` |
|
|
||||||
| `4-4` | `1455.05 ms, 3.63763 us/d` |
|
|
||||||
| `8-8` | `5485.06 ms, 6.85633 us/d` |
|
|
||||||
|
|
||||||
## Reference
|
## Reference
|
||||||
|
|
||||||
|
|||||||
BIN
performence.xlsx
Normal file
BIN
performence.xlsx
Normal file
Binary file not shown.
@ -153,8 +153,6 @@ public:
|
|||||||
fixed_pool(fixed_pool&& rhs) { this->swap(rhs); }
|
fixed_pool(fixed_pool&& rhs) { this->swap(rhs); }
|
||||||
fixed_pool& operator=(fixed_pool&& rhs) { this->swap(rhs); return (*this); }
|
fixed_pool& operator=(fixed_pool&& rhs) { this->swap(rhs); return (*this); }
|
||||||
|
|
||||||
~fixed_pool() { clear(); }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void swap(fixed_pool& rhs) {
|
void swap(fixed_pool& rhs) {
|
||||||
std::swap(this->alloc_ , rhs.alloc_);
|
std::swap(this->alloc_ , rhs.alloc_);
|
||||||
|
|||||||
@ -26,17 +26,22 @@ constexpr decltype(auto) static_switch(std::size_t i, std::index_sequence<N, I..
|
|||||||
static_switch(i, std::index_sequence<I...>{}, f, def);
|
static_switch(i, std::index_sequence<I...>{}, f, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename F, std::size_t...I>
|
||||||
|
constexpr void static_for(std::index_sequence<I...>, F&& f) {
|
||||||
|
[[maybe_unused]] auto expand = { (f(std::integral_constant<size_t, I>{}), 0)... };
|
||||||
|
}
|
||||||
|
|
||||||
template <std::size_t Size>
|
template <std::size_t Size>
|
||||||
auto& fixed() {
|
auto& fixed() {
|
||||||
static synchronized<fixed_pool<Size>> pool;
|
static synchronized<fixed_pool<Size>> pool;
|
||||||
return pool;
|
return pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
enum : std::size_t {
|
||||||
decltype(auto) choose(std::size_t size, F&& f) {
|
base_size = sizeof(void*)
|
||||||
enum : std::size_t { base_size = sizeof(void*) };
|
};
|
||||||
size = ((size - 1) & (~(base_size - 1))) + base_size;
|
|
||||||
return detail::static_switch(size, std::index_sequence<
|
using fixed_sequence_t = std::index_sequence<
|
||||||
base_size , base_size * 2 ,
|
base_size , base_size * 2 ,
|
||||||
base_size * 3 , base_size * 4 ,
|
base_size * 3 , base_size * 4 ,
|
||||||
base_size * 5 , base_size * 6 ,
|
base_size * 5 , base_size * 6 ,
|
||||||
@ -45,15 +50,26 @@ decltype(auto) choose(std::size_t size, F&& f) {
|
|||||||
base_size * 11, base_size * 12,
|
base_size * 11, base_size * 12,
|
||||||
base_size * 13, base_size * 14,
|
base_size * 13, base_size * 14,
|
||||||
base_size * 15, base_size * 16
|
base_size * 15, base_size * 16
|
||||||
>{}, [&f](auto index) {
|
>;
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
decltype(auto) choose(std::size_t size, F&& f) {
|
||||||
|
size = ((size - 1) & (~(base_size - 1))) + base_size;
|
||||||
|
return detail::static_switch(size, fixed_sequence_t {
|
||||||
|
}, [&f](auto index) {
|
||||||
return f(fixed<decltype(index)::value>());
|
return f(fixed<decltype(index)::value>());
|
||||||
}, [&f] { return f(static_alloc{}); });
|
}, [&f] {
|
||||||
|
return f(static_alloc{});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class pool_alloc {
|
class pool_alloc {
|
||||||
public:
|
public:
|
||||||
static constexpr void clear() {}
|
static void clear() {
|
||||||
static constexpr void swap(pool_alloc&) {}
|
static_for(fixed_sequence_t {}, [](auto index) {
|
||||||
|
fixed<decltype(index)::value>().clear();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static void* alloc(std::size_t size) {
|
static void* alloc(std::size_t size) {
|
||||||
return choose(size, [size](auto&& fp) { return fp.alloc(size); });
|
return choose(size, [size](auto&& fp) { return fp.alloc(size); });
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -80,6 +81,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
auto guard = std::unique_lock { lc_ };
|
||||||
|
std::vector<alloc_policy*> vec(allocs_.size());
|
||||||
|
std::size_t i = 0;
|
||||||
|
for (auto& pair : allocs_) {
|
||||||
|
vec[i++] = pair.second;
|
||||||
|
}
|
||||||
|
allocs_.clear();
|
||||||
|
guard.unlock();
|
||||||
|
for (auto alc : vec) delete alc;
|
||||||
|
}
|
||||||
|
|
||||||
void* alloc(std::size_t size) {
|
void* alloc(std::size_t size) {
|
||||||
return alc_info().alloc(size);
|
return alc_info().alloc(size);
|
||||||
}
|
}
|
||||||
@ -88,7 +101,7 @@ public:
|
|||||||
alc_info().free(p);
|
alc_info().free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free(void* p, std::size_t /*size*/) {
|
void free(void* p, std::size_t /*size*/) {
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -32,6 +32,8 @@ int main(int argc, char* argv[]) {
|
|||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
Q_UNUSED(app)
|
Q_UNUSED(app)
|
||||||
|
|
||||||
|
// QThread::sleep(5);
|
||||||
|
|
||||||
int failed_count = 0;
|
int failed_count = 0;
|
||||||
for (const auto& suite : (*suites__)) {
|
for (const auto& suite : (*suites__)) {
|
||||||
if (QTest::qExec(suite, argc, argv) != 0)
|
if (QTest::qExec(suite, argc, argv) != 0)
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "circ_elem_array.h"
|
#include "circ_elem_array.h"
|
||||||
#include "circ_queue.h"
|
#include "circ_queue.h"
|
||||||
|
#include "memory/resource.hpp"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -223,40 +224,11 @@ void Unit::test_prod_cons_1v3() {
|
|||||||
test_prod_cons<1, 3>();
|
test_prod_cons<1, 3>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int P, int C>
|
|
||||||
struct test_performance {
|
|
||||||
static void start() {
|
|
||||||
test_performance<P - 1, C - 1>::start();
|
|
||||||
test_prod_cons<P, C, false>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int C>
|
|
||||||
struct test_performance<1, C> {
|
|
||||||
static void start() {
|
|
||||||
test_performance<1, C - 1>::start();
|
|
||||||
test_prod_cons<1, C, false>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int P>
|
|
||||||
struct test_performance<P, 1> {
|
|
||||||
static void start() {
|
|
||||||
test_performance<P - 1, 1>::start();
|
|
||||||
test_prod_cons<P, 1, false>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct test_performance<1, 1> {
|
|
||||||
static void start() {
|
|
||||||
test_prod_cons<1, 1, false>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void Unit::test_prod_cons_performance() {
|
void Unit::test_prod_cons_performance() {
|
||||||
test_performance<1, 10>::start();
|
ipc::mem::detail::static_for(std::make_index_sequence<10>{}, [](auto index) {
|
||||||
test_prod_cons <1, 10>(); // test & verify
|
test_prod_cons<1, decltype(index)::value + 1, false>();
|
||||||
|
});
|
||||||
|
test_prod_cons<1, 10>(); // test & verify
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::test_queue() {
|
void Unit::test_queue() {
|
||||||
@ -269,10 +241,9 @@ void Unit::test_queue() {
|
|||||||
queue.attach(cq);
|
queue.attach(cq);
|
||||||
QVERIFY(queue.detach() != nullptr);
|
QVERIFY(queue.detach() != nullptr);
|
||||||
|
|
||||||
benchmark_prod_cons<1, 1, LoopCount>((ipc::circ::queue<msg_t>*)nullptr);
|
ipc::mem::detail::static_for(std::make_index_sequence<10>{}, [](auto index) {
|
||||||
benchmark_prod_cons<1, 2, LoopCount>((ipc::circ::queue<msg_t>*)nullptr);
|
benchmark_prod_cons<1, decltype(index)::value + 1, LoopCount>((ipc::circ::queue<msg_t>*)nullptr);
|
||||||
benchmark_prod_cons<1, 4, LoopCount>((ipc::circ::queue<msg_t>*)nullptr);
|
});
|
||||||
benchmark_prod_cons<1, 8, LoopCount>((ipc::circ::queue<msg_t>*)nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // internal-linkage
|
} // internal-linkage
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
#include "rw_lock.h"
|
#include "rw_lock.h"
|
||||||
|
#include "memory/resource.hpp"
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
@ -419,43 +420,11 @@ void Unit::test_route_rtt() {
|
|||||||
t2.join();
|
t2.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int P, int C, bool V = false>
|
|
||||||
struct test_performance {
|
|
||||||
template <typename T = ipc::route>
|
|
||||||
static void start() {
|
|
||||||
test_performance<P - 1, C - 1, V>::template start<T>();
|
|
||||||
test_prod_cons<T, P, C, V>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int C, bool V>
|
|
||||||
struct test_performance<1, C, V> {
|
|
||||||
template <typename T = ipc::route>
|
|
||||||
static void start() {
|
|
||||||
test_performance<1, C - 1, V>::template start<T>();
|
|
||||||
test_prod_cons<T, 1, C, V>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <int P, bool V>
|
|
||||||
struct test_performance<P, 1, V> {
|
|
||||||
template <typename T = ipc::route>
|
|
||||||
static void start() {
|
|
||||||
test_performance<P - 1, 1, V>::template start<T>();
|
|
||||||
test_prod_cons<T, P, 1, V>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <bool V>
|
|
||||||
struct test_performance<1, 1, V> {
|
|
||||||
template <typename T = ipc::route>
|
|
||||||
static void start() {
|
|
||||||
test_prod_cons<T, 1, 1, V>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void Unit::test_route_performance() {
|
void Unit::test_route_performance() {
|
||||||
test_performance<1, 10, true>::start();
|
ipc::mem::detail::static_for(std::make_index_sequence<10>{}, [](auto index) {
|
||||||
|
test_prod_cons<ipc::route, 1, decltype(index)::value + 1, false>();
|
||||||
|
});
|
||||||
|
test_prod_cons<ipc::route, 1, 10>(); // test & verify
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::test_channel() {
|
void Unit::test_channel() {
|
||||||
@ -518,9 +487,16 @@ void Unit::test_channel_rtt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Unit::test_channel_performance() {
|
void Unit::test_channel_performance() {
|
||||||
test_performance<1 , 10>::start<ipc::channel>();
|
ipc::mem::detail::static_for(std::make_index_sequence<10>{}, [](auto index) {
|
||||||
test_performance<10, 1 >::start<ipc::channel>();
|
test_prod_cons<ipc::channel, 1, decltype(index)::value + 1, false>();
|
||||||
test_performance<10, 10>::start<ipc::channel>();
|
});
|
||||||
|
ipc::mem::detail::static_for(std::make_index_sequence<10>{}, [](auto index) {
|
||||||
|
test_prod_cons<ipc::channel, decltype(index)::value + 1, 1, false>();
|
||||||
|
});
|
||||||
|
ipc::mem::detail::static_for(std::make_index_sequence<10>{}, [](auto index) {
|
||||||
|
test_prod_cons<ipc::channel, decltype(index)::value + 1,
|
||||||
|
decltype(index)::value + 1, false>();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} // internal-linkage
|
} // internal-linkage
|
||||||
|
|||||||
@ -88,6 +88,7 @@ void Unit::initTestCase() {
|
|||||||
sizes__.emplace_back(static_cast<std::size_t>(rdm()));
|
sizes__.emplace_back(static_cast<std::size_t>(rdm()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipc::mem::pool_alloc::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unit::cleanupTestCase() {
|
void Unit::cleanupTestCase() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user