diff --git a/build/test/CMakeLists.txt b/build/test/CMakeLists.txt old mode 100644 new mode 100755 index da9da36..2544ced --- a/build/test/CMakeLists.txt +++ b/build/test/CMakeLists.txt @@ -9,12 +9,12 @@ if(NOT MSVC) add_compile_options(-Wno-attributes -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-function) endif() -include_directories(../../include ../../src ../../test ../../test/capo) +include_directories(../../include ../../src ../../test) file(GLOB SRC_FILES ../../test/*.cpp) file(GLOB HEAD_FILES ../../test/*.h) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/../output) -link_directories(${EXECUTABLE_OUTPUT_PATH}) +link_directories(${EXECUTABLE_OUTPUT_PATH} ${CMAKE_SOURCE_DIR}/../test/gperftools) add_subdirectory(../ipc ipc.out) add_executable(${PROJECT_NAME} ${SRC_FILES} ${HEAD_FILES}) @@ -22,3 +22,5 @@ target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Test ipc) if(NOT MSVC) target_link_libraries(${PROJECT_NAME} pthread rt) endif() + +#target_link_libraries(${PROJECT_NAME} tcmalloc_minimal) diff --git a/build/test/test.pro b/build/test/test.pro index 3ac1cf3..e637248 100755 --- a/build/test/test.pro +++ b/build/test/test.pro @@ -18,7 +18,6 @@ DESTDIR = ../../output INCLUDEPATH += \ ../../test \ - ../../test/capo \ ../../include \ ../../src @@ -36,4 +35,6 @@ SOURCES += \ LIBS += \ -L$${DESTDIR} -lipc -unix:LIBS += -lrt -lpthread +unix:LIBS += \ +# -L../../test/gperftools -ltcmalloc_minimal \ + -lrt -lpthread diff --git a/performance.xlsx b/performance.xlsx index c2e7d5f..dbbccb1 100644 Binary files a/performance.xlsx and b/performance.xlsx differ diff --git a/src/memory/resource.h b/src/memory/resource.h index 13eea41..16ab19c 100644 --- a/src/memory/resource.h +++ b/src/memory/resource.h @@ -26,7 +26,14 @@ using static_async_fixed = static_wrapper>>; -using async_pool_alloc = /*static_alloc*/variable_wrapper; +using big_size_alloc = variable_wrapper::block_size(default_mapping_policy<>::classes_size), + default_mapping_policy<>::iter_size * 2 >>; + +using async_pool_alloc = variable_wrapper, + big_size_alloc>; template using allocator = allocator_wrapper; diff --git a/src/memory/wrapper.h b/src/memory/wrapper.h index add062d..1e525c8 100644 --- a/src/memory/wrapper.h +++ b/src/memory/wrapper.h @@ -335,30 +335,31 @@ public: /// Variable memory allocation wrapper //////////////////////////////////////////////////////////////// -template +template struct default_mapping_policy { enum : std::size_t { base_size = BaseSize, + iter_size = IterSize, classes_size = 32 }; static const std::size_t table[classes_size]; IPC_CONSTEXPR_ static std::size_t classify(std::size_t size) noexcept { - auto index = (size - 1) / base_size; + auto index = (size <= base_size) ? 0 : ((size - base_size - 1) / iter_size); return (index < classes_size) ? - // always uses default_mapping_policy::table + // always uses default_mapping_policy<>::table default_mapping_policy<>::table[index] : classes_size; } constexpr static std::size_t block_size(std::size_t value) noexcept { - return (value + 1) * base_size; + return base_size + (value + 1) * iter_size; } }; -template -const std::size_t default_mapping_policy::table[default_mapping_policy::classes_size] = { +template +const std::size_t default_mapping_policy::table[default_mapping_policy::classes_size] = { /* 1 - 8 ~ 32 */ 0 , 1 , 2 , 3 , /* 2 - 48 ~ 256 */ diff --git a/test/gperftools/libtcmalloc_minimal.so b/test/gperftools/libtcmalloc_minimal.so new file mode 100755 index 0000000..9f3c3fc Binary files /dev/null and b/test/gperftools/libtcmalloc_minimal.so differ diff --git a/test/gperftools/libtcmalloc_minimal.so.4 b/test/gperftools/libtcmalloc_minimal.so.4 new file mode 120000 index 0000000..74cc460 --- /dev/null +++ b/test/gperftools/libtcmalloc_minimal.so.4 @@ -0,0 +1 @@ +libtcmalloc_minimal.so \ No newline at end of file diff --git a/test/gperftools/libtcmalloc_minimal.so.4.5.3 b/test/gperftools/libtcmalloc_minimal.so.4.5.3 new file mode 120000 index 0000000..74cc460 --- /dev/null +++ b/test/gperftools/libtcmalloc_minimal.so.4.5.3 @@ -0,0 +1 @@ +libtcmalloc_minimal.so \ No newline at end of file diff --git a/test/gperftools/tcmalloc.h b/test/gperftools/tcmalloc.h new file mode 100755 index 0000000..7935081 --- /dev/null +++ b/test/gperftools/tcmalloc.h @@ -0,0 +1,163 @@ +// -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- +/* Copyright (c) 2003, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * --- + * Author: Sanjay Ghemawat + * .h file by Craig Silverstein + */ + +#ifndef TCMALLOC_TCMALLOC_H_ +#define TCMALLOC_TCMALLOC_H_ + +#include /* for size_t */ +#ifdef __cplusplus +#include /* for std::nothrow_t, std::align_val_t */ +#endif + +/* Define the version number so folks can check against it */ +#define TC_VERSION_MAJOR 2 +#define TC_VERSION_MINOR 7 +#define TC_VERSION_PATCH "" +#define TC_VERSION_STRING "gperftools 2.7" + +/* For struct mallinfo, if it's defined. */ +#if 1 +# include +#endif + +#ifndef PERFTOOLS_NOTHROW + +#if __cplusplus >= 201103L +#define PERFTOOLS_NOTHROW noexcept +#elif defined(__cplusplus) +#define PERFTOOLS_NOTHROW throw() +#else +# ifdef __GNUC__ +# define PERFTOOLS_NOTHROW __attribute__((__nothrow__)) +# else +# define PERFTOOLS_NOTHROW +# endif +#endif + +#endif + +#ifndef PERFTOOLS_DLL_DECL +# ifdef _WIN32 +# define PERFTOOLS_DLL_DECL __declspec(dllimport) +# else +# define PERFTOOLS_DLL_DECL +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + /* + * Returns a human-readable version string. If major, minor, + * and/or patch are not NULL, they are set to the major version, + * minor version, and patch-code (a string, usually ""). + */ + PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor, + const char** patch) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_free(void* ptr) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment, + size_t __size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr, + size_t align, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) PERFTOOLS_NOTHROW; + + PERFTOOLS_DLL_DECL void tc_malloc_stats(void) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) PERFTOOLS_NOTHROW; +#if 1 + PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHROW; +#endif + + /* + * This is an alias for MallocExtension::instance()->GetAllocatedSize(). + * It is equivalent to + * OS X: malloc_size() + * glibc: malloc_usable_size() + * Windows: _msize() + */ + PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_NOTHROW; + +#ifdef __cplusplus + PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_new(size_t size); + PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete(void* p) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_newarray(size_t size); + PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray(void* p) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + +#if 1 && __cplusplus >= 201703L + PERFTOOLS_DLL_DECL void* tc_new_aligned(size_t size, std::align_val_t al); + PERFTOOLS_DLL_DECL void* tc_new_aligned_nothrow(size_t size, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_delete_aligned_nothrow(void* p, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void* tc_newarray_aligned(size_t size, std::align_val_t al); + PERFTOOLS_DLL_DECL void* tc_newarray_aligned_nothrow(size_t size, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_aligned(void* p, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_sized_aligned(void* p, size_t size, std::align_val_t al) PERFTOOLS_NOTHROW; + PERFTOOLS_DLL_DECL void tc_deletearray_aligned_nothrow(void* p, std::align_val_t al, + const std::nothrow_t&) PERFTOOLS_NOTHROW; +#endif +} +#endif + +/* We're only un-defining for public */ +#if !defined(GPERFTOOLS_CONFIG_H_) + +#undef PERFTOOLS_NOTHROW + +#endif /* GPERFTOOLS_CONFIG_H_ */ + +#endif /* #ifndef TCMALLOC_TCMALLOC_H_ */ diff --git a/test/test.h b/test/test.h index f39e70d..715361b 100644 --- a/test/test.h +++ b/test/test.h @@ -13,8 +13,8 @@ # include // abi::__cxa_demangle #endif/*__GNUC__*/ -#include "stopwatch.hpp" -#include "spin_lock.hpp" +#include "capo/stopwatch.hpp" +#include "capo/spin_lock.hpp" class TestSuite : public QObject { diff --git a/test/test_ipc.cpp b/test/test_ipc.cpp index 44a4f78..befabe3 100644 --- a/test/test_ipc.cpp +++ b/test/test_ipc.cpp @@ -13,9 +13,9 @@ #include #include -#include "stopwatch.hpp" -#include "spin_lock.hpp" -#include "random.hpp" +#include "capo/stopwatch.hpp" +#include "capo/spin_lock.hpp" +#include "capo/random.hpp" #include "ipc.h" #include "rw_lock.h" diff --git a/test/test_mem.cpp b/test/test_mem.cpp index 325eb1a..5ee3363 100644 --- a/test/test_mem.cpp +++ b/test/test_mem.cpp @@ -3,11 +3,13 @@ #include #include -#include "random.hpp" +#include "capo/random.hpp" #include "memory/resource.h" #include "pool_alloc.h" +//#include "gperftools/tcmalloc.h" + #include "test.h" namespace { @@ -23,15 +25,13 @@ 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 = 1000000; +constexpr int DataMin = 4; +constexpr int DataMax = 256; +constexpr int LoopCount = 100000; std::vector sizes__; @@ -96,18 +96,13 @@ void benchmark_alloc() { test_stopwatch sw; sw.start(); - for (std::size_t x = 0; x < 10; ++x) + for (std::size_t k = 0; k < 100; ++k) 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(); + sw.print_elapsed<1>(DataMin, DataMax, LoopCount * 100); } template @@ -131,6 +126,7 @@ void benchmark_alloc() { for (auto& w : works) { w = std::thread {[&, pid] { sw.start(); + for (std::size_t k = 0; k < 10; ++k) for (std::size_t x = 0; x < 2; ++x) { for(std::size_t n = 0; n < LoopCount; ++n) { int m = mode.ix_[x][n]; @@ -146,7 +142,7 @@ void benchmark_alloc() { } } if ((fini.fetch_add(1, std::memory_order_relaxed) + 1) == ThreadsN) { - sw.print_elapsed<1>(DataMin, DataMax, LoopCount * ThreadsN); + sw.print_elapsed<1>(DataMin, DataMax, LoopCount * 10 * ThreadsN); } }}; ++pid; @@ -171,19 +167,29 @@ struct test_performance { } }; -void Unit::test_static() { - test_performance::start(); - test_performance::start(); - test_performance::start(); -} +//class tc_alloc { +//public: +// static void clear() {} -void Unit::test_pool() { -// test_performance::start(); -// for (;;) { - test_performance::start(); - test_performance::start(); - test_performance::start(); +// 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); +// } +//}; + +#define TEST_ALLOC_TYPE /*ipc::mem::static_alloc*/ ipc::mem::async_pool_alloc /*tc_alloc*/ + +void Unit::test_alloc_free() { +// benchmark_alloc (); +// test_performance::start(); + + benchmark_alloc (); + test_performance::start(); + test_performance::start(); + test_performance::start(); } } // internal-linkage