optimize memory allocator for big size memory

This commit is contained in:
zhangyi 2019-07-05 18:53:30 +08:00
parent 981124520c
commit c8cedf11cf
12 changed files with 223 additions and 41 deletions

6
build/test/CMakeLists.txt Normal file → Executable file
View File

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

View File

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

Binary file not shown.

View File

@ -26,7 +26,14 @@ using static_async_fixed =
static_wrapper<async_wrapper<fixed_alloc<
Size, chunk_variable_alloc >>>;
using async_pool_alloc = /*static_alloc*/variable_wrapper<static_async_fixed>;
using big_size_alloc = variable_wrapper<static_async_fixed,
default_mapping_policy<
default_mapping_policy<>::block_size(default_mapping_policy<>::classes_size),
default_mapping_policy<>::iter_size * 2 >>;
using async_pool_alloc = variable_wrapper<static_async_fixed,
default_mapping_policy<>,
big_size_alloc>;
template <typename T>
using allocator = allocator_wrapper<T, async_pool_alloc>;

View File

@ -335,30 +335,31 @@ public:
/// Variable memory allocation wrapper
////////////////////////////////////////////////////////////////
template <std::size_t BaseSize = sizeof(void*)>
template <std::size_t BaseSize = 0, std::size_t IterSize = sizeof(void*)>
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<sizeof(void*)>::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 <std::size_t B>
const std::size_t default_mapping_policy<B>::table[default_mapping_policy<B>::classes_size] = {
template <std::size_t B, std::size_t I>
const std::size_t default_mapping_policy<B, I>::table[default_mapping_policy<B, I>::classes_size] = {
/* 1 - 8 ~ 32 */
0 , 1 , 2 , 3 ,
/* 2 - 48 ~ 256 */

Binary file not shown.

View File

@ -0,0 +1 @@
libtcmalloc_minimal.so

View File

@ -0,0 +1 @@
libtcmalloc_minimal.so

163
test/gperftools/tcmalloc.h Executable file
View File

@ -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 <opensource@google.com>
* .h file by Craig Silverstein <opensource@google.com>
*/
#ifndef TCMALLOC_TCMALLOC_H_
#define TCMALLOC_TCMALLOC_H_
#include <stddef.h> /* for size_t */
#ifdef __cplusplus
#include <new> /* 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 <malloc.h>
#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_ */

View File

@ -13,8 +13,8 @@
# include <cxxabi.h> // 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
{

View File

@ -13,9 +13,9 @@
#include <limits>
#include <utility>
#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"

View File

@ -3,11 +3,13 @@
#include <atomic>
#include <cstddef>
#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<std::size_t> 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<ipc::mem::static_alloc>();
benchmark_alloc<ipc::mem::async_pool_alloc>();
sw.print_elapsed<1>(DataMin, DataMax, LoopCount * 100);
}
template <typename AllocT, typename ModeT, int ThreadsN>
@ -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<AllocT, ModeT, 1> {
}
};
void Unit::test_static() {
test_performance<ipc::mem::static_alloc, alloc_FIFO , 8>::start();
test_performance<ipc::mem::static_alloc, alloc_LIFO , 8>::start();
test_performance<ipc::mem::static_alloc, alloc_random, 8>::start();
}
//class tc_alloc {
//public:
// static void clear() {}
void Unit::test_pool() {
// test_performance<ipc::mem::pool_alloc, alloc_FIFO , 8>::start();
// for (;;) {
test_performance<ipc::mem::pool_alloc, alloc_FIFO , 8>::start();
test_performance<ipc::mem::pool_alloc, alloc_LIFO , 8>::start();
test_performance<ipc::mem::pool_alloc, alloc_random, 8>::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_ALLOC_TYPE>();
// test_performance<TEST_ALLOC_TYPE, alloc_FIFO , 24>::start();
benchmark_alloc <TEST_ALLOC_TYPE>();
test_performance<TEST_ALLOC_TYPE, alloc_FIFO , 16>::start();
test_performance<TEST_ALLOC_TYPE, alloc_LIFO , 16>::start();
test_performance<TEST_ALLOC_TYPE, alloc_random, 16>::start();
}
} // internal-linkage