Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: add mimalloc support #984

Merged
merged 2 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/compiler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ jobs:
rm -f *.tar.gz
- name: Build
run: |
./tools/build --variant gui --arch ${{ matrix.arch }} --system mingw -build-test -use-tcmalloc=false \
./tools/build --variant gui --arch ${{ matrix.arch }} --system mingw -build-test \
--clang-path $PWD/third_party/llvm-mingw-20231128-ucrt-ubuntu-20.04-x86_64 -no-packaging
- name: Populate depedencies (Tests-i686)
if: ${{ matrix.arch == 'i686' }}
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,6 @@
[submodule "third_party/gperftools"]
path = third_party/gperftools
url = https://github.com/Chilledheart/gperftools
[submodule "third_party/mimalloc"]
path = third_party/mimalloc
url = https://github.com/Chilledheart/mimalloc
112 changes: 91 additions & 21 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -434,11 +434,21 @@ option(BUILD_SHARED_LIBS "Build with shared libraries." OFF)
option(BUILD_TESTS "Build with test." OFF)
option(OPTIMIZED_PROTOC "Force protobuf compiler to be built with optimization" OFF)

option(USE_TCMALLOC "Build with tcmalloc" OFF)
cmake_dependent_option(
USE_TCMALLOC "Build with tcmalloc" OFF
"LINUX" OFF)
cmake_dependent_option(
USE_SYSTEM_TCMALLOC "Build with system or vendored tcmalloc" OFF
USE_TCMALLOC OFF)

cmake_dependent_option(
USE_MIMALLOC "Use mimalloc" OFF
"NOT USE_TCMALLOC; NOT WIN32; NOT APPLE; NOT ANDROID; NOT OHOS" OFF)

cmake_dependent_option(
USE_SYSTEM_MIMALLOC "Use system or vendored mimalloc" OFF
USE_MIMALLOC OFF)

option(USE_LIBCXX "Build with libc++" ON)

option(USE_NGHTTP2 "Build with libnghttp2" ON)
Expand Down Expand Up @@ -1908,13 +1918,22 @@ endif()
if (NOT WIN32 AND NOT APPLE)
check_library_exists(c pipe2 "" HAVE_PIPE2)
check_library_exists(c dup3 "" HAVE_DUP3)
# for android mallinfo2 is alias to mallinfo
check_symbol_exists(mallinfo malloc.h HAVE_MALLINFO)
check_symbol_exists(mallinfo2 malloc.h HAVE_MALLINFO2)
endif()
if (HAVE_PIPE2)
add_definitions(-DHAVE_PIPE2)
endif()
if (HAVE_DUP3)
add_definitions(-DHAVE_DUP3)
endif()
if (HAVE_MALLINFO)
add_definitions(-DHAVE_MALLINFO)
endif()
if (HAVE_MALLINFO2)
add_definitions(-DHAVE_MALLINFO2)
endif()

# *****************************************************************************************
# Core Support Libraries
Expand Down Expand Up @@ -2320,24 +2339,10 @@ set(SUPPORT_LIBS
# only support platform: linux
# mac: __thread limitation
#

if (USE_TCMALLOC AND NOT USE_SYSTEM_TCMALLOC)
if (WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
if (NOT (OS_X86 OR OS_X64 OR OS_ARM OR OS_AARCH64 OR OS_MIPS OR OS_MIPS64 OR OS_RISCV64 OR OS_LOONGARCH64))
message(WARNING "tcmalloc: arch ${CMAKE_SYSTEM_PROCESSOR} is not supported, disabling...")
set(USE_TCMALLOC OFF)
endif()
# FIXME tcmalloc's preamble patcher doesn't support arm64 assembly
if (WIN32 AND OS_AARCH64)
message(WARNING "tcmalloc: arm64 windows is not supported, disabling...")
set(USE_TCMALLOC OFF)
endif()
# FIXME windows binaries doesn't pass UtilsTest.GetHomeDir for both mingw and msvc builds
if (WIN32)
message(WARNING "tcmalloc: mingw and msvc builds are not supported, disabling...")
set(USE_TCMALLOC OFF)
endif()
else()
message(WARNING "tcmalloc: only Linux and FreeBSD are supported, disabling...")
if (NOT (OS_X86 OR OS_X64 OR OS_ARM OR OS_AARCH64 OR OS_MIPS OR OS_MIPS64 OR OS_RISCV64 OR OS_LOONGARCH64))
message(WARNING "tcmalloc: arch ${CMAKE_SYSTEM_PROCESSOR} is not supported, disabling...")
set(USE_TCMALLOC OFF)
endif()
endif()
Expand Down Expand Up @@ -2389,6 +2394,7 @@ elseif (USE_TCMALLOC)
${SUPPORT_DEFINITIONS}
)
set(SUPPORT_INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}/third_party/gperftools
third_party/gperftools/src
${SUPPORT_INCLUDE_DIRS}
)
Expand All @@ -2406,6 +2412,69 @@ elseif (USE_TCMALLOC)
endif()
endif()

# *****************************************************************************************
# mimalloc Library
# *****************************************************************************************

if (USE_SYSTEM_MIMALLOC)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(MIMALLOC mimalloc)
endif()
if(NOT MIMALLOC_FOUND)
message(STATUS "System mimalloc not found, using bundled one")
set(USE_SYSTEM_MIMALLOC FALSE)
endif()
if (USE_LIBCXX)
message(STATUS "Cannot use system mimalloc with custom libc++, using bundled one")
set(USE_SYSTEM_MIMALLOC FALSE)
endif()
endif()

# By default, we build a bundled mimalloc and statically-link it to
# mold. If you want to dynamically link to the system's
# libmimalloc.so, pass -DUSE_SYSTEM_MIMALLOC=ON.
if (USE_MIMALLOC AND USE_SYSTEM_MIMALLOC)
message(STATUS "Compiling with system tcmalloc support")
list(APPEND YASS_APP_FEATURES "system mimalloc")

set(MIMALLOC_LIB mimalloc)

set(SUPPORT_DEFINITIONS
HAVE_MIMALLOC
${SUPPORT_DEFINITIONS}
)
set(SUPPORT_LIBS
${SUPPORT_LIBS}
${MIMALLOC_LIB}
)

elseif(USE_MIMALLOC)
message(STATUS "Compiling with bundled mimalloc support")

set(MI_BUILD_STATIC ON CACHE INTERNAL "")
set(MI_BUILD_SHARED OFF CACHE INTERNAL "")
set(MI_BUILD_OBJECT OFF CACHE INTERNAL "")
set(MI_BUILD_TESTS OFF CACHE INTERNAL "")
set(MI_ENABLE_INSTALL OFF CACHE INTERNAL "")
set(MI_LIBC_MUSL "${USE_MUSL}" CACHE INTERNAL "")
add_subdirectory(third_party/mimalloc EXCLUDE_FROM_ALL)
target_compile_definitions(mimalloc-static PRIVATE MI_USE_ENVIRON=0)

set(MIMALLOC_LIB mimalloc-static)

set(SUPPORT_DEFINITIONS
HAVE_MIMALLOC
${SUPPORT_DEFINITIONS}
)
set(SUPPORT_LIBS
${SUPPORT_LIBS}
${MIMALLOC_LIB}
)

list(APPEND YASS_APP_FEATURES "mimalloc")
endif()

# *****************************************************************************************
# re2 Library
# *****************************************************************************************
Expand Down Expand Up @@ -2657,9 +2726,6 @@ foreach(source ${BCM_ASM_SOURCES})
set_source_files_properties(${source} PROPERTIES GENERATED true)
endforeach()

set_target_properties(bssl PROPERTIES EXCLUDE_FROM_ALL TRUE)
set_target_properties(decrepit PROPERTIES EXCLUDE_FROM_ALL TRUE)

if (BORINGSSL_BUILD_TESTS)
add_custom_target(check_boringssl
COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir
Expand Down Expand Up @@ -3716,6 +3782,10 @@ if (USE_TCMALLOC)
target_link_libraries(yass_core PUBLIC ${TCMALLOC_LIB})
endif()

if (USE_MIMALLOC)
target_link_libraries(yass_core PUBLIC ${MIMALLOC_LIB})
endif()

target_include_directories(yass_core PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/third_party/googleurl-override
${CMAKE_CURRENT_SOURCE_DIR}/third_party/googleurl/polyfills
Expand Down
6 changes: 3 additions & 3 deletions src/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,14 @@ int main(int argc, const char* argv[]) {
#ifdef SIGQUIT
signals.add(SIGQUIT, ec);
#endif
#if defined(HAVE_TCMALLOC) && defined(SIGUSR1)
#if defined(SIGUSR1)
signals.add(SIGUSR1, ec);
#endif
std::function<void(asio::error_code, int)> cb;
cb = [&](asio::error_code /*ec*/, int signal_number) {
#if defined(HAVE_TCMALLOC) && defined(SIGUSR1)
#if defined(SIGUSR1)
if (signal_number == SIGUSR1) {
PrintTcmallocStats();
PrintMallocStats();
signals.async_wait(cb);
return;
}
Expand Down
26 changes: 26 additions & 0 deletions src/config/config_version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
#include "feature.h"
#include "version.h"

#ifdef HAVE_TCMALLOC
#include <gperftools/tcmalloc.h>
#endif

#ifdef HAVE_MIMALLOC
#include <mimalloc.h>
#endif

namespace config {

static void ParseConfigFileOption(int argc, const char** argv) {
Expand Down Expand Up @@ -59,6 +67,12 @@ static void ParseConfigFileOption(int argc, const char** argv) {
std::cout << absl::flags_internal::ShortProgramInvocationName() << " " << YASS_APP_TAG << std::endl;
std::cout << "Last Change: " << YASS_APP_LAST_CHANGE << std::endl;
std::cout << "Features: " << YASS_APP_FEATURES << std::endl;
#ifdef HAVE_TCMALLOC
std::cerr << "TCMALLOC: " << tc_version(nullptr, nullptr, nullptr) << std::endl;
#endif
#ifdef HAVE_MIMALLOC
std::cerr << "MIMALLOC: " << mi_version() << std::endl;
#endif
#ifndef NDEBUG
std::cout << "Debug build (NDEBUG not #defined)" << std::endl;
#endif
Expand All @@ -72,6 +86,12 @@ static void ParseConfigFileOption(int argc, const char** argv) {
std::cerr << "Application starting: " << YASS_APP_TAG << std::endl;
std::cerr << "Last Change: " << YASS_APP_LAST_CHANGE << std::endl;
std::cerr << "Features: " << YASS_APP_FEATURES << std::endl;
#ifdef HAVE_TCMALLOC
std::cerr << "TCMALLOC: " << tc_version(nullptr, nullptr, nullptr) << std::endl;
#endif
#ifdef HAVE_MIMALLOC
std::cerr << "MIMALLOC: " << mi_version() << std::endl;
#endif
#ifndef NDEBUG
std::cerr << "Debug build (NDEBUG not #defined)\n" << std::endl;
#endif
Expand All @@ -96,6 +116,12 @@ void ReadConfigFileAndArguments(int argc, const char** argv) {
LOG(WARNING) << "Application starting: " << YASS_APP_TAG << " type: " << ProgramTypeToStr(pType);
LOG(WARNING) << "Last Change: " << YASS_APP_LAST_CHANGE;
LOG(WARNING) << "Features: " << YASS_APP_FEATURES;
#ifdef HAVE_TCMALLOC
LOG(WARNING) << "TCMALLOC: " << tc_version(nullptr, nullptr, nullptr);
#endif
#ifdef HAVE_MIMALLOC
LOG(WARNING) << "MIMALLOC: " << mi_version();
#endif
#ifndef NDEBUG
LOG(WARNING) << "Debug build (NDEBUG not #defined)\n";
#endif
Expand Down
43 changes: 41 additions & 2 deletions src/core/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@
#include <gperftools/malloc_extension.h>
#endif

#ifdef HAVE_MIMALLOC
#include <mimalloc.h>
#endif

#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2) || BUILDFLAG(IS_FREEBSD)
#include <malloc.h>
#endif

#include <absl/flags/flag.h>
#include <absl/flags/internal/program_name.h>
#include <absl/strings/str_cat.h>
Expand Down Expand Up @@ -385,8 +393,8 @@ bool IsProgramConsole(int fd) {
}
#endif

void PrintMallocStats() {
#ifdef HAVE_TCMALLOC
void PrintTcmallocStats() {
constexpr const char* properties[] = {
"generic.current_allocated_bytes",
"generic.heap_size",
Expand All @@ -402,8 +410,39 @@ void PrintTcmallocStats() {
LOG(ERROR) << "TCMALLOC: " << property << " = " << size << " bytes";
}
}
}
#elif defined(HAVE_MIMALLOC)
auto printer = [](const char* msg, void* arg) { LOG(ERROR) << "MIMALLOC: " << msg; };
mi_stats_print_out(printer, nullptr);
#elif defined(HAVE_MALLINFO2) && !defined(MEMORY_SANITIZER)
struct mallinfo2 info = mallinfo2();
LOG(ERROR) << "MALLOC: non-mmapped space allocated from system: " << info.arena;
LOG(ERROR) << "MALLOC: number of free chunks: " << info.ordblks;
LOG(ERROR) << "MALLOC: number of fastbin blocks: " << info.smblks;
LOG(ERROR) << "MALLOC: number of mmapped regions: " << info.hblks;
LOG(ERROR) << "MALLOC: space in mmapped regions: " << info.hblkhd;
LOG(ERROR) << "MALLOC: space available in freed fastbin blocks: " << info.fsmblks;
LOG(ERROR) << "MALLOC: total allocated space: " << info.uordblks;
LOG(ERROR) << "MALLOC: total free space: " << info.fordblks;
LOG(ERROR) << "MALLOC: top-most, releasable (via malloc_trim) space: " << info.keepcost;
#elif defined(HAVE_MALLINFO) && !defined(MEMORY_SANITIZER)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
struct mallinfo info = mallinfo();
#pragma GCC diagnostic pop
LOG(ERROR) << "MALLOC: non-mmapped space allocated from system: " << info.arena;
LOG(ERROR) << "MALLOC: number of free chunks: " << info.ordblks;
LOG(ERROR) << "MALLOC: number of fastbin blocks: " << info.smblks;
LOG(ERROR) << "MALLOC: number of mmapped regions: " << info.hblks;
LOG(ERROR) << "MALLOC: space in mmapped regions: " << info.hblkhd;
LOG(ERROR) << "MALLOC: space available in freed fastbin blocks: " << info.fsmblks;
LOG(ERROR) << "MALLOC: total allocated space: " << info.uordblks;
LOG(ERROR) << "MALLOC: total free space: " << info.fordblks;
LOG(ERROR) << "MALLOC: top-most, releasable (via malloc_trim) space: " << info.keepcost;
#elif BUILDFLAG(IS_FREEBSD)
auto printer = [](void* data, const char* msg) { LOG(ERROR) << "MALLOC: " << msg; };
malloc_stats_print(printer, nullptr, nullptr);
#endif
}

template <typename T>
static void HumanReadableByteCountBinT(T* ss, uint64_t bytes) {
Expand Down
4 changes: 1 addition & 3 deletions src/core/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,7 @@ PlatformFile OpenReadFile(const std::string& path);
PlatformFile OpenReadFile(const std::wstring& path);
#endif

#ifdef HAVE_TCMALLOC
void PrintTcmallocStats();
#endif
void PrintMallocStats();

#ifdef __APPLE__
#if BUILDFLAG(IS_IOS)
Expand Down
6 changes: 3 additions & 3 deletions src/server/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,14 @@ int main(int argc, const char* argv[]) {
#ifdef SIGQUIT
signals.add(SIGQUIT, ec);
#endif
#if defined(HAVE_TCMALLOC) && defined(SIGUSR1)
#if defined(SIGUSR1)
signals.add(SIGUSR1, ec);
#endif
std::function<void(asio::error_code, int)> cb;
cb = [&](asio::error_code /*ec*/, int signal_number) {
#if defined(HAVE_TCMALLOC) && defined(SIGUSR1)
#if defined(SIGUSR1)
if (signal_number == SIGUSR1) {
PrintTcmallocStats();
PrintMallocStats();
signals.async_wait(cb);
return;
}
Expand Down
4 changes: 1 addition & 3 deletions src/ss_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -800,9 +800,7 @@ int main(int argc, char** argv) {

int ret = RUN_ALL_TESTS();

#ifdef HAVE_TCMALLOC
PrintTcmallocStats();
#endif
PrintMallocStats();

#ifdef HAVE_CURL
curl_global_cleanup();
Expand Down
Loading
Loading