#include #include #include #include #include #include "capo/random.hpp" #include "libipc/memory/resource.h" #include "libipc/pool_alloc.h" // #include "gperftools/tcmalloc.h" #include "test.h" #include "thread_pool.h" namespace { constexpr int DataMin = 4; constexpr int DataMax = 256; constexpr int LoopCount = 8388608; constexpr int ThreadMax = 8; // constexpr int DataMin = 256; // constexpr int DataMax = 512; // constexpr int LoopCount = 2097152; std::vector sizes__; std::vector ptr_cache__[ThreadMax]; template struct alloc_ix_t { static std::vector ix_; static bool inited_; alloc_ix_t() { if (inited_) return; inited_ = true; M::init(); } template static int index(std::size_t /*pid*/, std::size_t /*k*/, std::size_t n) { return ix_[n]; } }; template std::vector alloc_ix_t::ix_(LoopCount); template bool alloc_ix_t::inited_ = false; struct alloc_FIFO : alloc_ix_t { static void init() { for (int i = 0; i < LoopCount; ++i) { ix_[static_cast(i)] = i; } } }; struct alloc_LIFO : alloc_ix_t { static void init() { for (int i = 0; i < LoopCount; ++i) { ix_[static_cast(i)] = i; } } template static int index(std::size_t pid, std::size_t k, std::size_t n) { constexpr static int CacheSize = LoopCount / ThreadsN; if (k) { return ix_[(CacheSize * (2 * pid + 1)) - 1 - n]; } else return ix_[n]; } }; struct alloc_Random : alloc_ix_t { static void init() { capo::random<> rdm_index(0, LoopCount - 1); for (int i = 0; i < LoopCount; ++i) { ix_[static_cast(i)] = rdm_index(); } } }; struct Init { Init() { capo::random<> rdm{ DataMin, DataMax }; for (int i = 0; i < LoopCount; ++i) { sizes__.emplace_back(static_cast(rdm())); } for (auto& vec : ptr_cache__) { vec.resize(LoopCount, nullptr); } } } init__; template void benchmark_alloc(char const * message) { std::string msg = std::to_string(ThreadsN) + "\t" + message; constexpr static int CacheSize = LoopCount / ThreadsN; ipc_ut::sender().start(static_cast(ThreadsN)); ipc_ut::test_stopwatch sw; for (int pid = 0; pid < ThreadsN; ++pid) { ipc_ut::sender() << [&, pid] { sw.start(); for (int n = (CacheSize * pid); n < (CacheSize * (pid + 1)); ++n) { std::size_t s = sizes__[n]; AllocT::free(AllocT::alloc(s), s); } }; } ipc_ut::sender().wait_for_done(); sw.print_elapsed<1>(DataMin, DataMax, LoopCount, msg.c_str()); } template void benchmark_alloc(char const * message) { std::string msg = std::to_string(ThreadsN) + "\t" + message; constexpr static int CacheSize = LoopCount / ThreadsN; ModeT mode; ipc_ut::sender().start(static_cast(ThreadsN)); ipc_ut::test_stopwatch sw; for (int pid = 0; pid < ThreadsN; ++pid) { ipc_ut::sender() << [&, pid] { auto& vec = ptr_cache__[pid]; sw.start(); for (std::size_t k = 0; k < 2; ++k) for (int n = (CacheSize * pid); n < (CacheSize * (pid + 1)); ++n) { int m = mode.template index(pid, k, n); void*& p = vec[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; } } }; } ipc_ut::sender().wait_for_done(); sw.print_elapsed<1>(DataMin, DataMax, LoopCount, msg.c_str()); } template struct test_performance { static void start(char const * message) { test_performance::start(message); benchmark_alloc(message); } }; template struct test_performance { static void start(char const * message) { benchmark_alloc(message); } }; template struct test_performance { static void start(char const * message) { test_performance::start(message); benchmark_alloc(message); } }; template struct test_performance { static void start(char const * message) { benchmark_alloc(message); } }; // class tc_alloc { // public: // static void clear() {} // static void* alloc(std::size_t size) { // return size ? tc_malloc(size) : nullptr; // } // static void free(void* p, std::size_t size) { // tc_free_sized(p, size); // } // }; /* TEST(Memory, static_alloc) { test_performance::start("alloc-free"); test_performance::start("alloc-FIFO"); test_performance::start("alloc-LIFO"); test_performance::start("alloc-Rand"); } TEST(Memory, pool_alloc) { test_performance::start("alloc-free"); test_performance::start("alloc-FIFO"); test_performance::start("alloc-LIFO"); test_performance::start("alloc-Rand"); } */ // TEST(Memory, tc_alloc) { // test_performance::start(); // test_performance::start(); // test_performance::start(); // test_performance::start(); // } } // internal-linkage