#include #include #include #include #include "random.hpp" #include "memory/resource.h" #include "pool_alloc.h" #include "test.h" namespace { class Unit : public TestSuite { Q_OBJECT const char* name() const { return "test_mem"; } private slots: void initTestCase(); void test_alloc_free(); void test_static(); void test_pool(); } unit__; #include "test_mem.moc" constexpr int DataMin = sizeof(void*); constexpr int DataMax = sizeof(void*) * 16; constexpr int LoopCount = 10000000; std::vector sizes__; template struct alloc_ix_t { static std::vector ix_[2]; static bool inited_; }; template std::vector alloc_ix_t::ix_[2] = { std::vector(LoopCount), std::vector(LoopCount) }; template bool alloc_ix_t::inited_ = false; struct alloc_random : alloc_ix_t { 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(i)] = ix_[1][static_cast(i)] = rdm_index(); } } }; struct alloc_LIFO : alloc_ix_t { alloc_LIFO() { if (inited_) return; inited_ = true; for (int i = 0, n = LoopCount - 1; i < LoopCount; ++i, --n) { ix_[0][static_cast(i)] = ix_[1][static_cast(n)] = i; } } }; struct alloc_FIFO : alloc_ix_t { alloc_FIFO() { if (inited_) return; inited_ = true; for (int i = 0; i < LoopCount; ++i) { ix_[0][static_cast(i)] = ix_[1][static_cast(i)] = i; } } }; void Unit::initTestCase() { TestSuite::initTestCase(); capo::random<> rdm { DataMin, DataMax }; for (int i = 0; i < LoopCount; ++i) { sizes__.emplace_back(static_cast(rdm())); } } template void benchmark_alloc() { std::cout << std::endl << type_name() << std::endl; test_stopwatch sw; sw.start(); for (std::size_t x = 0; x < 10; ++x) for (std::size_t n = 0; n < LoopCount; ++n) { std::size_t s = sizes__[n]; AllocT::free(AllocT::alloc(s), s); } sw.print_elapsed<1>(DataMin, DataMax, LoopCount * 10); } void Unit::test_alloc_free() { benchmark_alloc(); benchmark_alloc(); } template void benchmark_alloc() { std::cout << std::endl << "[Threads: " << ThreadsN << ", Mode: " << type_name() << "] " << type_name() << std::endl; std::vector 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(m)]; std::size_t s = sizes__[static_cast(m)]; if (p == nullptr) { p = AllocT::alloc(s); } else { AllocT::free(p, s); p = nullptr; } } } if ((fini.fetch_add(1, std::memory_order_relaxed) + 1) == ThreadsN) { sw.print_elapsed<1>(DataMin, DataMax, LoopCount * ThreadsN); } }}; ++pid; } sw.start(); for (auto& w : works) w.join(); } template struct test_performance { static void start() { test_performance::start(); benchmark_alloc(); } }; template struct test_performance { static void start() { benchmark_alloc(); } }; void Unit::test_static() { test_performance::start(); test_performance::start(); test_performance::start(); } void Unit::test_pool() { test_performance::start(); test_performance::start(); test_performance::start(); } } // internal-linkage