mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
add test for pool_alloc
This commit is contained in:
parent
20caf4d1e1
commit
319bcdab2f
@ -5,7 +5,7 @@ add_compile_definitions(__IPC_LIBRARY__)
|
|||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_compile_options("/std:c++17")
|
add_compile_options("/std:c++17")
|
||||||
else()
|
else()
|
||||||
add_compile_options("-std=gnu++1z")
|
add_compile_options("-std=gnu++1z -O2")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories("../include")
|
include_directories("../include")
|
||||||
|
|||||||
@ -24,7 +24,8 @@ SOURCES += \
|
|||||||
../test/main.cpp \
|
../test/main.cpp \
|
||||||
../test/test_shm.cpp \
|
../test/test_shm.cpp \
|
||||||
../test/test_circ.cpp \
|
../test/test_circ.cpp \
|
||||||
../test/test_ipc.cpp
|
../test/test_ipc.cpp \
|
||||||
|
../test/test_mem.cpp
|
||||||
|
|
||||||
LIBS += \
|
LIBS += \
|
||||||
-L$${DESTDIR} -lipc
|
-L$${DESTDIR} -lipc
|
||||||
|
|||||||
@ -16,14 +16,14 @@ namespace mem {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename F, typename D>
|
template <typename F, typename D>
|
||||||
constexpr decltype(auto) switch_constexpr(std::size_t /*i*/, std::index_sequence<>, F&& /*f*/, D&& def) {
|
constexpr decltype(auto) static_switch(std::size_t /*i*/, std::index_sequence<>, F&& /*f*/, D&& def) {
|
||||||
return def();
|
return def();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F, typename D, std::size_t N, std::size_t...I>
|
template <typename F, typename D, std::size_t N, std::size_t...I>
|
||||||
constexpr decltype(auto) switch_constexpr(std::size_t i, std::index_sequence<N, I...>, F&& f, D&& def) {
|
constexpr decltype(auto) static_switch(std::size_t i, std::index_sequence<N, I...>, F&& f, D&& def) {
|
||||||
return (i == N) ? f(std::integral_constant<size_t, N>{}) :
|
return (i == N) ? f(std::integral_constant<size_t, N>{}) :
|
||||||
switch_constexpr(i, std::index_sequence<I...>{}, f, def);
|
static_switch(i, std::index_sequence<I...>{}, f, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -40,7 +40,7 @@ private:
|
|||||||
static decltype(auto) choose(std::size_t size, F&& f) {
|
static decltype(auto) choose(std::size_t size, F&& f) {
|
||||||
enum : std::size_t { base_size = sizeof(void*) };
|
enum : std::size_t { base_size = sizeof(void*) };
|
||||||
size = ((size - 1) & (~(base_size - 1))) + base_size;
|
size = ((size - 1) & (~(base_size - 1))) + base_size;
|
||||||
return detail::switch_constexpr(size, std::index_sequence<
|
return detail::static_switch(size, 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 ,
|
||||||
|
|||||||
@ -40,11 +40,16 @@ struct test_stopwatch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <int Factor>
|
||||||
void print_elapsed(int N, int M, int Loops) {
|
void print_elapsed(int N, int M, int Loops) {
|
||||||
auto ts = sw_.elapsed<std::chrono::microseconds>();
|
auto ts = sw_.elapsed<std::chrono::microseconds>();
|
||||||
std::cout << "[" << N << ":" << M << ", " << Loops << "] "
|
std::cout << "[" << N << ":" << M << ", " << Loops << "] "
|
||||||
<< "performance: " << (ts / 1000.0) << " ms, "
|
<< "performance: " << (ts / 1000.0) << " ms, "
|
||||||
<< (double(ts) / double(Loops * N)) << " us/d" << std::endl;
|
<< (double(ts) / double(Factor ? (Loops * Factor) : (Loops * N))) << " us/d" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_elapsed(int N, int M, int Loops) {
|
||||||
|
print_elapsed<0>(N, M, Loops);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -462,7 +462,7 @@ void Unit::test_channel() {
|
|||||||
std::thread t2 {[&] {
|
std::thread t2 {[&] {
|
||||||
ipc::channel cc { "my-ipc-channel" };
|
ipc::channel cc { "my-ipc-channel" };
|
||||||
cc.wait_for_recv(1);
|
cc.wait_for_recv(1);
|
||||||
for (std::size_t i = 0; i < (std::min)(100, LoopCount); ++i) {
|
for (std::size_t i = 0; i < static_cast<std::size_t>((std::min)(100, LoopCount)); ++i) {
|
||||||
std::cout << "sending: " << i << "-[" << datas__[i].size() << "]" << std::endl;
|
std::cout << "sending: " << i << "-[" << datas__[i].size() << "]" << std::endl;
|
||||||
cc.send(datas__[i]);
|
cc.send(datas__[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
166
test/test_mem.cpp
Normal file
166
test/test_mem.cpp
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "random.hpp"
|
||||||
|
|
||||||
|
#include "memory/resource.hpp"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class Unit : public TestSuite {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
const char* name() const {
|
||||||
|
return "test_mem";
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initTestCase();
|
||||||
|
void cleanupTestCase();
|
||||||
|
|
||||||
|
void test_alloc();
|
||||||
|
} unit__;
|
||||||
|
|
||||||
|
#include "test_mem.moc"
|
||||||
|
|
||||||
|
constexpr int DataMin = sizeof(void*);
|
||||||
|
constexpr int DataMax = sizeof(void*) * 16;
|
||||||
|
constexpr int LoopCount = 1000000;
|
||||||
|
|
||||||
|
std::vector<std::size_t> sizes__;
|
||||||
|
|
||||||
|
template <typename M>
|
||||||
|
struct alloc_ix_t {
|
||||||
|
static std::vector<int> ix_[2];
|
||||||
|
static bool inited_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename M>
|
||||||
|
std::vector<int> alloc_ix_t<M>::ix_[2] = { std::vector<int>(LoopCount), std::vector<int>(LoopCount) };
|
||||||
|
template <typename M>
|
||||||
|
bool alloc_ix_t<M>::inited_ = false;
|
||||||
|
|
||||||
|
struct alloc_random : alloc_ix_t<alloc_random> {
|
||||||
|
alloc_random() {
|
||||||
|
if (inited_) return;
|
||||||
|
inited_ = true;
|
||||||
|
capo::random<> rdm_index(0, LoopCount - 1);
|
||||||
|
for (int i = 0; i < LoopCount; ++i) {
|
||||||
|
ix_[0][static_cast<std::size_t>(i)] =
|
||||||
|
ix_[1][static_cast<std::size_t>(i)] = rdm_index();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct alloc_LIFO : alloc_ix_t<alloc_LIFO> {
|
||||||
|
alloc_LIFO() {
|
||||||
|
if (inited_) return;
|
||||||
|
inited_ = true;
|
||||||
|
for (int i = 0, n = LoopCount - 1; i < LoopCount; ++i, --n) {
|
||||||
|
ix_[0][static_cast<std::size_t>(i)] =
|
||||||
|
ix_[1][static_cast<std::size_t>(n)] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct alloc_FIFO : alloc_ix_t<alloc_FIFO> {
|
||||||
|
alloc_FIFO() {
|
||||||
|
if (inited_) return;
|
||||||
|
inited_ = true;
|
||||||
|
for (int i = 0; i < LoopCount; ++i) {
|
||||||
|
ix_[0][static_cast<std::size_t>(i)] =
|
||||||
|
ix_[1][static_cast<std::size_t>(i)] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Unit::initTestCase() {
|
||||||
|
TestSuite::initTestCase();
|
||||||
|
|
||||||
|
capo::random<> rdm { DataMin, DataMax };
|
||||||
|
for (int i = 0; i < LoopCount; ++i) {
|
||||||
|
sizes__.emplace_back(static_cast<std::size_t>(rdm()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Unit::cleanupTestCase() {
|
||||||
|
sizes__.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename AllocT, typename ModeT, int ThreadsN>
|
||||||
|
void benchmark_alloc() {
|
||||||
|
std::cout << std::endl
|
||||||
|
<< "[Threads: " << ThreadsN << ", Mode: " << type_name<ModeT>() << "] "
|
||||||
|
<< type_name<AllocT>() << std::endl;
|
||||||
|
|
||||||
|
std::vector<void*> ptrs[ThreadsN];
|
||||||
|
for (auto& vec : ptrs) {
|
||||||
|
vec.resize(LoopCount);
|
||||||
|
}
|
||||||
|
ModeT mode;
|
||||||
|
|
||||||
|
std::atomic_int fini { 0 };
|
||||||
|
test_stopwatch sw;
|
||||||
|
|
||||||
|
std::thread works[ThreadsN];
|
||||||
|
int pid = 0;
|
||||||
|
|
||||||
|
for (auto& w : works) {
|
||||||
|
w = std::thread {[&, pid] {
|
||||||
|
sw.start();
|
||||||
|
for (std::size_t x = 0; x < 2; ++x) {
|
||||||
|
for(std::size_t n = 0; n < LoopCount; ++n) {
|
||||||
|
int m = mode.ix_[x][n];
|
||||||
|
void* (& p) = ptrs[pid][static_cast<std::size_t>(m)];
|
||||||
|
std::size_t s = sizes__[static_cast<std::size_t>(m)];
|
||||||
|
if (p == nullptr) {
|
||||||
|
p = AllocT::alloc(s);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
AllocT::free(p, s);
|
||||||
|
p = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (++fini == ThreadsN) {
|
||||||
|
sw.print_elapsed<1>(DataMin, DataMax, LoopCount);
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
++pid;
|
||||||
|
}
|
||||||
|
sw.start();
|
||||||
|
|
||||||
|
for (auto& w : works) w.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename AllocT, typename ModeT, int ThreadsN>
|
||||||
|
struct test_performance {
|
||||||
|
static void start() {
|
||||||
|
test_performance<AllocT, ModeT, ThreadsN - 1>::start();
|
||||||
|
benchmark_alloc<AllocT, ModeT, ThreadsN>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename AllocT, typename ModeT>
|
||||||
|
struct test_performance<AllocT, ModeT, 1> {
|
||||||
|
static void start() {
|
||||||
|
benchmark_alloc<AllocT, ModeT, 1>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Unit::test_alloc() {
|
||||||
|
// malloc
|
||||||
|
test_performance<ipc::mem::static_alloc, alloc_random, 8>::start();
|
||||||
|
test_performance<ipc::mem::static_alloc, alloc_LIFO , 8>::start();
|
||||||
|
test_performance<ipc::mem::static_alloc, alloc_FIFO , 8>::start();
|
||||||
|
// pool-alloc
|
||||||
|
test_performance<ipc::mem::pool_alloc , alloc_random, 8>::start();
|
||||||
|
test_performance<ipc::mem::pool_alloc , alloc_LIFO , 8>::start();
|
||||||
|
test_performance<ipc::mem::pool_alloc , alloc_FIFO , 8>::start();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // internal-linkage
|
||||||
Loading…
x
Reference in New Issue
Block a user