add test for pool_alloc

This commit is contained in:
mutouyun 2018-12-30 16:28:14 +08:00
parent 20caf4d1e1
commit 319bcdab2f
6 changed files with 180 additions and 8 deletions

View File

@ -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")

View File

@ -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

View File

@ -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 ,

View File

@ -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);
} }
}; };

View File

@ -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
View 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