From efb94f6da17d9f2cf75c49f54e159d5490be1caf Mon Sep 17 00:00:00 2001 From: wangdan Date: Tue, 31 Aug 2021 14:55:17 +0800 Subject: [PATCH 1/6] feat: support jemalloc --- bin/FindJemalloc.cmake | 83 +++++++++++++++++++++++++++++++++++++++ bin/dsn.cmake | 23 +++++++++++ run.sh | 10 ++++- scripts/linux/build.sh | 8 ++++ thirdparty/CMakeLists.txt | 15 +++++++ 5 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 bin/FindJemalloc.cmake diff --git a/bin/FindJemalloc.cmake b/bin/FindJemalloc.cmake new file mode 100644 index 0000000000..bc7c09c807 --- /dev/null +++ b/bin/FindJemalloc.cmake @@ -0,0 +1,83 @@ +############################################################################## +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +############################################################################## + +find_path(Jemalloc_INCLUDE_DIRS + NAMES jemalloc/jemalloc.h + PATHS ${DSN_THIRDPARTY_ROOT}/include + NO_DEFAULT_PATH +) + +find_library(Jemalloc_SHARED_LIBRARIES + NAMES jemalloc + PATHS ${DSN_THIRDPARTY_ROOT}/lib + NO_DEFAULT_PATH +) + +find_library(Jemalloc_STATIC_LIBRARIES + NAMES libjemalloc_pic.a + PATHS ${DSN_THIRDPARTY_ROOT}/lib + NO_DEFAULT_PATH +) + +if(Jemalloc_INCLUDE_DIRS AND Jemalloc_SHARED_LIBRARIES AND Jemalloc_STATIC_LIBRARIES) + set(Jemalloc_FOUND TRUE) +else() + set(Jemalloc_FOUND FALSE) +endif() + +if(Jemalloc_FOUND) + message(STATUS "Found jemalloc header files: ${Jemalloc_INCLUDE_DIRS}") + message(STATUS "Found jemalloc shared libs: ${Jemalloc_SHARED_LIBRARIES}") + message(STATUS "Found jemalloc static libs: ${Jemalloc_STATIC_LIBRARIES}") +else() + if(Jemalloc_FIND_REQUIRED) + message(FATAL_ERROR "Not found jemalloc in ${DSN_THIRDPARTY_ROOT}") + endif() +endif() + +mark_as_advanced( + Jemalloc_INCLUDE_DIRS + Jemalloc_SHARED_LIBRARIES + Jemalloc_STATIC_LIBRARIES +) + +# Reuse JeMalloc::JeMalloc from RocksDB::rocksdb +# as the only exposed target +if(Jemalloc_FOUND AND NOT (TARGET JeMalloc::JeMalloc)) + if("${JEMALLOC_LIB_TYPE}" STREQUAL "SHARED") + add_library(JeMalloc::JeMalloc SHARED IMPORTED) + set_target_properties(JeMalloc::JeMalloc PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${Jemalloc_INCLUDE_DIRS} + IMPORTED_LOCATION ${Jemalloc_SHARED_LIBRARIES} + ) + message(STATUS "Use jemalloc lib type: ${JEMALLOC_LIB_TYPE}") + message(STATUS "Use jemalloc lib: ${Jemalloc_SHARED_LIBRARIES}") + elseif("${JEMALLOC_LIB_TYPE}" STREQUAL "STATIC") + add_library(JeMalloc::JeMalloc STATIC IMPORTED) + set_target_properties(JeMalloc::JeMalloc PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${Jemalloc_INCLUDE_DIRS} + IMPORTED_LINK_INTERFACE_LANGUAGES "C;CXX" + IMPORTED_LOCATION ${Jemalloc_STATIC_LIBRARIES} + ) + message(STATUS "Use jemalloc lib type: ${JEMALLOC_LIB_TYPE}") + message(STATUS "Use jemalloc lib: ${Jemalloc_STATIC_LIBRARIES}") + else() + message(FATAL_ERROR "Invalid jemalloc lib type: ${JEMALLOC_LIB_TYPE}") + endif() +endif() diff --git a/bin/dsn.cmake b/bin/dsn.cmake index 7f4f908989..afd5305f68 100644 --- a/bin/dsn.cmake +++ b/bin/dsn.cmake @@ -28,6 +28,17 @@ message(STATUS "ENABLE_GCOV = ${ENABLE_GCOV}") option(ENABLE_GPERF "Enable gperftools (for tcmalloc)" ON) message(STATUS "ENABLE_GPERF = ${ENABLE_GPERF}") +option(USE_JEMALLOC "Use jemalloc" OFF) +message(STATUS "USE_JEMALLOC = ${USE_JEMALLOC}") + +if(ENABLE_GPERF AND USE_JEMALLOC) + message(FATAL_ERROR "cannot enable both gperftools and jemalloc simultaneously") +endif() + +if(USE_JEMALLOC) + set(JEMALLOC_LIB_TYPE "STATIC") +endif() + # ================================================================== # @@ -271,6 +282,12 @@ function(dsn_setup_system_libs) add_definitions(-DDSN_ENABLE_GPERF) endif() + if(USE_JEMALLOC) + find_package(Jemalloc REQUIRED) + set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} JeMalloc::JeMalloc) + add_definitions(-DDSN_USE_JEMALLOC) + endif() + set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} ${CMAKE_THREAD_LIBS_INIT} # the thread library found by FindThreads @@ -310,6 +327,12 @@ function(dsn_setup_thirdparty_libs) find_package(snappy) find_package(zstd) find_package(lz4) + if(USE_JEMALLOC) + # expose JeMalloc::JeMalloc to whoever wants to link RocksDB::rocksdb + # set(JEMALLOC_ROOT_DIR ${TP_OUTPUT}) + # find_package(JeMalloc REQUIRED) + find_package(Jemalloc REQUIRED) + endif() find_package(RocksDB REQUIRED) # libhdfs diff --git a/run.sh b/run.sh index 85c51fc87b..0e5941db2e 100755 --- a/run.sh +++ b/run.sh @@ -52,6 +52,7 @@ function usage_build() echo " --notest build without building unit tests, default no" echo " --disable_gperf build without gperftools, this flag is mainly used" echo " to enable valgrind memcheck, default no" + echo " --use_jemalloc build with jemalloc" echo " --skip_thirdparty whether to skip building thirdparties, default no" echo " --check whether to perform code check before building" echo " --sanitizer build with sanitizer to check potential problems, @@ -80,6 +81,7 @@ function run_build() RUN_VERBOSE=NO NO_TEST=NO DISABLE_GPERF=NO + USE_JEMALLOC=NO SKIP_THIRDPARTY=NO CHECK=NO SANITIZER="" @@ -130,6 +132,10 @@ function run_build() --disable_gperf) DISABLE_GPERF=YES ;; + --use_jemalloc) + DISABLE_GPERF=YES + USE_JEMALLOC=YES + ;; --skip_thirdparty) SKIP_THIRDPARTY=YES ;; @@ -187,7 +193,7 @@ function run_build() mkdir -p build pushd build cmake .. -DCMAKE_C_COMPILER=$C_COMPILER -DCMAKE_CXX_COMPILER=$CXX_COMPILER -DCMAKE_BUILD_TYPE=Release \ - -DROCKSDB_PORTABLE=${ROCKSDB_PORTABLE} + -DROCKSDB_PORTABLE=${ROCKSDB_PORTABLE} -DUSE_JEMALLOC=${USE_JEMALLOC} make -j$JOB_NUM exit_if_fail $? popd @@ -211,7 +217,7 @@ function run_build() ONLY_BUILD="$ONLY_BUILD" CLEAR="$CLEAR" JOB_NUM="$JOB_NUM" \ ENABLE_GCOV="$ENABLE_GCOV" SANITIZER="$SANITIZER" \ RUN_VERBOSE="$RUN_VERBOSE" TEST_MODULE="$TEST_MODULE" NO_TEST="$NO_TEST" \ - DISABLE_GPERF="$DISABLE_GPERF" $scripts_dir/build.sh + DISABLE_GPERF="$DISABLE_GPERF" USE_JEMALLOC="$USE_JEMALLOC" $scripts_dir/build.sh } ##################### diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh index 8908978a63..e4069eb8b5 100755 --- a/scripts/linux/build.sh +++ b/scripts/linux/build.sh @@ -87,6 +87,14 @@ else echo "DISABLE_GPERF=NO" fi +if [ "$USE_JEMALLOC" == "YES" ] +then + echo "USE_JEMALLOC=YES" + CMAKE_OPTIONS="$CMAKE_OPTIONS -DUSE_JEMALLOC=ON" +else + echo "USE_JEMALLOC=NO" +fi + if [ ! -z "$SANITIZER" ] then echo "SANITIZER=$SANITIZER" diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 512d99a35c..05725bf194 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -316,12 +316,25 @@ ExternalProject_Add(s2geometry DEPENDS googletest ) +option(USE_JEMALLOC "use jemalloc" OFF) +message(STATUS "USE_JEMALLOC = ${USE_JEMALLOC}") + +ExternalProject_Add(jemalloc + URL https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 + URL_MD5 3d41fbf006e6ebffd489bdb304d009ae + CONFIGURE_COMMAND ./configure --prefix=${TP_OUTPUT} --enable-cxx --enable-stats --enable-prof + BUILD_COMMAND make + INSTALL_COMMAND make install + BUILD_IN_SOURCE 1 + ) + option(ROCKSDB_PORTABLE "build a portable binary" OFF) ExternalProject_Add(rocksdb URL ${OSS_URL_PREFIX}/pegasus-rocksdb-6.6.4-compatible.zip https://github.com/XiaoMi/pegasus-rocksdb/archive/v6.6.4-compatible.zip URL_MD5 595b21fbe681dcf126c4cccda46f1cbb + DEPENDS jemalloc CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${TP_OUTPUT} -DWITH_LZ4=ON -DWITH_ZSTD=ON @@ -330,6 +343,8 @@ ExternalProject_Add(rocksdb -DWITH_TESTS=OFF -DWITH_GFLAGS=OFF -DUSE_RTTI=ON + -DWITH_JEMALLOC=${USE_JEMALLOC} + -DJEMALLOC_ROOT_DIR=${TP_OUTPUT} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DPORTABLE=${ROCKSDB_PORTABLE} From 7bb85af37929e50dd6fcf54e89d3616cc2f53319 Mon Sep 17 00:00:00 2001 From: wangdan Date: Mon, 6 Sep 2021 16:23:58 +0800 Subject: [PATCH 2/6] feat: support jemalloc --- src/replica/replica_stub.cpp | 139 ++++++++++++++++++ src/replica/replica_stub.h | 9 ++ src/runtime/service_api_c.cpp | 6 + src/utils/je_ctl.cpp | 268 ++++++++++++++++++++++++++++++++++ src/utils/je_ctl.h | 61 ++++++++ thirdparty/CMakeLists.txt | 2 +- 6 files changed, 484 insertions(+), 1 deletion(-) create mode 100644 src/utils/je_ctl.cpp create mode 100644 src/utils/je_ctl.h diff --git a/src/replica/replica_stub.cpp b/src/replica/replica_stub.cpp index 52e677ab72..a4736eac39 100644 --- a/src/replica/replica_stub.cpp +++ b/src/replica/replica_stub.cpp @@ -57,6 +57,8 @@ #include #ifdef DSN_ENABLE_GPERF #include +#elif defined(DSN_USE_JEMALLOC) +#include "utils/je_ctl.h" #endif #include #include @@ -99,6 +101,15 @@ replica_stub::replica_stub(replica_state_subscriber subscriber /*= nullptr*/, _get_tcmalloc_status_command = nullptr; _max_reserved_memory_percentage_command = nullptr; _release_all_reserved_memory_command = nullptr; +#elif defined(DSN_USE_JEMALLOC) + _set_jemalloc_all_arenas_dirty_decay_ms_command = nullptr; + _set_jemalloc_all_arenas_muzzy_decay_ms_command = nullptr; + _decay_jemalloc_all_arenas_command = nullptr; + _purge_jemalloc_all_arenas_command = nullptr; + _get_jemalloc_configs_command = nullptr; + _get_jemalloc_summary_stats_command = nullptr; + _get_jemalloc_brief_arena_stats_command = nullptr; + _get_jemalloc_detailed_stats_command = nullptr; #endif _replica_state_subscriber = subscriber; _is_long_subscriber = is_long_subscriber; @@ -2404,6 +2415,116 @@ void replica_stub::register_ctrl_command() auto release_bytes = gc_tcmalloc_memory(true); return "OK, release_bytes=" + std::to_string(release_bytes); }); +#elif defined(DSN_USE_JEMALLOC) + _set_jemalloc_all_arenas_dirty_decay_ms_command = ::dsn::command_manager::instance().register_command( + {"replica.set-jemalloc-all-arenas-dirty-decay-ms"}, + "replica.set-jemalloc-all-arenas-dirty-decay-ms [num | DEFAULT]", + "set dirty decay ms for all arenas memory of jemalloc", + [](const std::vector &args) { + if (args.empty()) { + // show current value + std::string info; + dsn::utils::je_ctl_get_all_arenas_dirty_decay_ms_info(&info); + return info; + } + + int64_t dirty_decay_ms = 0; + if (args[0] == "DEFAULT") { + // set to default value + dirty_decay_ms = 10000; + } else if (!dsn::buf2int64(args[0], dirty_decay_ms)) { + return std::string("ERR: invalid arguments"); + } + + std::string msg; + dsn::utils::je_ctl_set_all_arenas_dirty_decay_ms(static_cast(dirty_decay_ms), &msg); + return msg; + }); + + _set_jemalloc_all_arenas_muzzy_decay_ms_command = ::dsn::command_manager::instance().register_command( + {"replica.set-jemalloc-all-arenas-muzzy-decay-ms"}, + "replica.set-jemalloc-all-arenas-muzzy-decay-ms [num | DEFAULT]", + "set muzzy decay ms for all arenas memory of jemalloc", + [](const std::vector &args) { + if (args.empty()) { + // show current value + std::string info; + dsn::utils::je_ctl_get_all_arenas_muzzy_decay_ms_info(&info); + return info; + } + + int64_t muzzy_decay_ms = 0; + if (args[0] == "DEFAULT") { + // set to default value + muzzy_decay_ms = 10000; + } else if (!dsn::buf2int64(args[0], muzzy_decay_ms)) { + return std::string("ERR: invalid arguments"); + } + + std::string msg; + dsn::utils::je_ctl_set_all_arenas_muzzy_decay_ms(static_cast(muzzy_decay_ms), &msg); + return msg; + }); + + _decay_jemalloc_all_arenas_command = ::dsn::command_manager::instance().register_command( + {"replica.decay-jemalloc-all-arenas"}, + "replica.decay-jemalloc-all-arenas - decay all arenas memory of jemalloc", + "decay all arenas memory of jemalloc", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_decay_all_arenas(&msg); + return msg; + }); + + _purge_jemalloc_all_arenas_command = ::dsn::command_manager::instance().register_command( + {"replica.purge-jemalloc-all-arenas"}, + "replica.purge-jemalloc-all-arenas - purge all arenas memory of jemalloc", + "purge all arenas memory of jemalloc", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_purge_all_arenas(&msg); + return msg; + }); + + _get_jemalloc_configs_command = ::dsn::command_manager::instance().register_command( + {"replica.get-jemalloc-configs"}, + "replica.get-jemalloc-configs - get configs of jemalloc", + "get configs of jemalloc", + [](const std::vector &args) { + std::string stats("\n"); + dsn::utils::je_dump_configs(&stats); + return stats; + }); + + _get_jemalloc_summary_stats_command = ::dsn::command_manager::instance().register_command( + {"replica.get-jemalloc-summary-stats"}, + "replica.get-jemalloc-summary-stats - get summary stats of jemalloc", + "get summary stats of jemalloc", + [](const std::vector &args) { + std::string stats("\n"); + dsn::utils::je_dump_summary_stats(&stats); + return stats; + }); + + _get_jemalloc_brief_arena_stats_command = ::dsn::command_manager::instance().register_command( + {"replica.get-jemalloc-brief-arena-stats"}, + "replica.get-jemalloc-brief-arena-stats - get brief_arena stats of jemalloc", + "get brief arena stats of jemalloc", + [](const std::vector &args) { + std::string stats("\n"); + dsn::utils::je_dump_brief_arena_stats(&stats); + return stats; + }); + + _get_jemalloc_detailed_stats_command = ::dsn::command_manager::instance().register_command( + {"replica.get-jemalloc-detailed-stats"}, + "replica.get-jemalloc-detailed-stats - get detailed stats of jemalloc", + "get detailed stats of jemalloc", + [](const std::vector &args) { + std::string stats("\n"); + dsn::utils::je_dump_detailed_stats(&stats); + return stats; + }); #endif _max_concurrent_bulk_load_downloading_count_command = dsn::command_manager::instance().register_command( @@ -2566,6 +2687,15 @@ void replica_stub::close() UNREGISTER_VALID_HANDLER(_get_tcmalloc_status_command); UNREGISTER_VALID_HANDLER(_max_reserved_memory_percentage_command); UNREGISTER_VALID_HANDLER(_release_all_reserved_memory_command); +#elif defined(DSN_USE_JEMALLOC) + UNREGISTER_VALID_HANDLER(_set_jemalloc_all_arenas_dirty_decay_ms_command); + UNREGISTER_VALID_HANDLER(_set_jemalloc_all_arenas_muzzy_decay_ms_command); + UNREGISTER_VALID_HANDLER(_decay_jemalloc_all_arenas_command); + UNREGISTER_VALID_HANDLER(_purge_jemalloc_all_arenas_command); + UNREGISTER_VALID_HANDLER(_get_jemalloc_configs_command); + UNREGISTER_VALID_HANDLER(_get_jemalloc_summary_stats_command); + UNREGISTER_VALID_HANDLER(_get_jemalloc_brief_arena_stats_command); + UNREGISTER_VALID_HANDLER(_get_jemalloc_detailed_stats_command); #endif UNREGISTER_VALID_HANDLER(_max_concurrent_bulk_load_downloading_count_command); @@ -2581,6 +2711,15 @@ void replica_stub::close() _get_tcmalloc_status_command = nullptr; _max_reserved_memory_percentage_command = nullptr; _release_all_reserved_memory_command = nullptr; +#elif defined(DSN_USE_JEMALLOC) + _set_jemalloc_all_arenas_dirty_decay_ms_command = nullptr; + _set_jemalloc_all_arenas_muzzy_decay_ms_command = nullptr; + _decay_jemalloc_all_arenas_command = nullptr; + _purge_jemalloc_all_arenas_command = nullptr; + _get_jemalloc_configs_command = nullptr; + _get_jemalloc_summary_stats_command = nullptr; + _get_jemalloc_brief_arena_stats_command = nullptr; + _get_jemalloc_detailed_stats_command = nullptr; #endif _max_concurrent_bulk_load_downloading_count_command = nullptr; diff --git a/src/replica/replica_stub.h b/src/replica/replica_stub.h index 3b93f325b2..c9feca784b 100644 --- a/src/replica/replica_stub.h +++ b/src/replica/replica_stub.h @@ -375,6 +375,15 @@ class replica_stub : public serverlet, public ref_counter dsn_handle_t _get_tcmalloc_status_command; dsn_handle_t _max_reserved_memory_percentage_command; dsn_handle_t _release_all_reserved_memory_command; +#elif defined(DSN_USE_JEMALLOC) + dsn_handle_t _set_jemalloc_all_arenas_dirty_decay_ms_command; + dsn_handle_t _set_jemalloc_all_arenas_muzzy_decay_ms_command; + dsn_handle_t _decay_jemalloc_all_arenas_command; + dsn_handle_t _purge_jemalloc_all_arenas_command; + dsn_handle_t _get_jemalloc_configs_command; + dsn_handle_t _get_jemalloc_summary_stats_command; + dsn_handle_t _get_jemalloc_brief_arena_stats_command; + dsn_handle_t _get_jemalloc_detailed_stats_command; #endif dsn_handle_t _max_concurrent_bulk_load_downloading_count_command; diff --git a/src/runtime/service_api_c.cpp b/src/runtime/service_api_c.cpp index 649af2611b..f42e86c457 100644 --- a/src/runtime/service_api_c.cpp +++ b/src/runtime/service_api_c.cpp @@ -45,6 +45,8 @@ #ifdef DSN_ENABLE_GPERF #include +#elif defined(DSN_USE_JEMALLOC) +#include "utils/je_ctl.h" #endif #include "service_engine.h" @@ -439,6 +441,10 @@ bool run(const char *config_file, // init logging dsn_log_init(spec.logging_factory_name, spec.dir_log, dsn_log_prefixed_message_func); +#if !defined(DSN_ENABLE_GPERF) && defined(DSN_USE_JEMALLOC) + dsn::utils::je_initialize(); +#endif + // prepare minimum necessary ::dsn::service_engine::instance().init_before_toollets(spec); diff --git a/src/utils/je_ctl.cpp b/src/utils/je_ctl.cpp new file mode 100644 index 0000000000..f6909ec04c --- /dev/null +++ b/src/utils/je_ctl.cpp @@ -0,0 +1,268 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#ifdef DSN_USE_JEMALLOC + +#include "je_ctl.h" + +#include +#include +#include +#include + +#define STRINGIFY_HELPER(x) #x +#define STRINGIFY(x) STRINGIFY_HELPER(x) + +namespace dsn { +namespace utils { + +static bool je_ctl_check_err(const char *action, int err, std::string *err_msg) +{ + std::string msg; + if (dsn_likely(err == 0)) { + msg = fmt::format("{} successfully", action); + } else { + msg = fmt::format( + "failed to {}: errno={}, message={}", action, err, dsn::utils::safe_strerror(err)); + } + + ddebug_f(" {}", msg); + + if (err_msg != nullptr) { + *err_msg = std::move(msg); + } + + return err == 0; +} + +template +static bool je_ctl_check_set_err(const char *name, T val, int err, std::string *err_msg) +{ + std::string action(fmt::format("set {} to {}", name, val)); + return je_ctl_check_err(action.c_str(), err, err_msg); +} + +template +static bool je_ctl_set_num(const char *name, T val, std::string *err_msg) +{ + int je_ret = mallctl(name, nullptr, nullptr, &val, sizeof(val)); + return je_ctl_check_set_err(name, val, je_ret, err_msg); +} + +/* +static bool je_ctl_set_str(const char *name, const char *val, std::string *err_msg) +{ + void *v = static_cast(const_cast(val)); + int je_ret = mallctl(name, nullptr, nullptr, v, sizeof(val)); + return je_ctl_check_set_err(name, val, je_ret, err_msg); +} +*/ + +static bool je_ctl_set_void(const char *name, std::string *err_msg) +{ + int je_ret = mallctl(name, nullptr, nullptr, nullptr, 0); + return je_ctl_check_err(name, je_ret, err_msg); +} + +static bool je_ctl_check_get_err(const char *name, int err, std::string *err_msg) +{ + std::string action(fmt::format("get {}", name)); + return je_ctl_check_err(action.c_str(), err, err_msg); +} + +template +static bool je_ctl_get_num(const char *name, T &val, std::string *err_msg) +{ + size_t size = sizeof(val); + int je_ret = mallctl(name, &val, &size, nullptr, 0); + return je_ctl_check_get_err(name, je_ret, err_msg); +} + +void je_initialize() +{ + bool enable_je_bg_thread = true; + je_ctl_set_num("background_thread", enable_je_bg_thread, nullptr); +} + +static bool je_ctl_get_narenas(unsigned &narenas, std::string *err_msg) +{ + return je_ctl_get_num("arenas.narenas", narenas, err_msg); +} + +static std::string build_arena_name(unsigned index, const char *sub_name) +{ + return fmt::format("arena.{}.{}", index, sub_name); +} + +template +static bool je_ctl_set_arena_num(unsigned index, const char *sub_name, T val, std::string *err_msg) +{ + std::string name(build_arena_name(index, sub_name)); + return je_ctl_set_num(name.c_str(), val, err_msg); +} + +template +static bool je_ctl_get_arena_num(unsigned index, const char *sub_name, T &val, std::string *err_msg) +{ + std::string name(build_arena_name(index, sub_name)); + return je_ctl_get_num(name.c_str(), val, err_msg); +} + +template +static bool je_ctl_set_all_arenas_num(const char *sub_name, T val, std::string *err_msg) +{ + unsigned narenas = 0; + if (!je_ctl_get_narenas(narenas, err_msg)) { + return false; + } + + for (unsigned i = 0; i < narenas; ++i) { + if (!je_ctl_set_arena_num(i, sub_name, val, err_msg)) { + return false; + } + } + + *err_msg = fmt::format("set {} for all arenas successfully", sub_name); + return true; +} + +template +static bool +je_ctl_get_all_arenas_num(const char *sub_name, std::vector &nums, std::string *err_msg) +{ + unsigned narenas = 0; + if (!je_ctl_get_narenas(narenas, err_msg)) { + return false; + } + + nums.clear(); + nums.reserve(narenas); + for (unsigned i = 0; i < narenas; ++i) { + T val; + if (!je_ctl_get_arena_num(i, sub_name, val, err_msg)) { + return false; + } + nums.push_back(val); + } + + *err_msg = fmt::format("get {} for all arenas successfully", sub_name); + return true; +} + +template +static bool je_ctl_get_all_arenas_num_info(const char *sub_name, std::string *info) +{ + std::vector nums; + if (!je_ctl_get_all_arenas_num(sub_name, nums, info)) { + return false; + } + + for (size_t i = 0; i < nums.size(); ++i) { + info->append(fmt::format("\narena[{}]: {}", i, nums[i])); + } + return true; +} + +bool je_ctl_set_all_arenas_dirty_decay_ms(ssize_t dirty_decay_ms, std::string *err_msg) +{ + return je_ctl_set_all_arenas_num("dirty_decay_ms", dirty_decay_ms, err_msg); +} + +bool je_ctl_get_all_arenas_dirty_decay_ms(std::vector &nums, std::string *err_msg) +{ + return je_ctl_get_all_arenas_num("dirty_decay_ms", nums, err_msg); +} + +bool je_ctl_get_all_arenas_dirty_decay_ms_info(std::string *info) +{ + return je_ctl_get_all_arenas_num_info("dirty_decay_ms", info); +} + +bool je_ctl_set_all_arenas_muzzy_decay_ms(ssize_t muzzy_decay_ms, std::string *err_msg) +{ + return je_ctl_set_all_arenas_num("muzzy_decay_ms", muzzy_decay_ms, err_msg); +} + +bool je_ctl_get_all_arenas_muzzy_decay_ms(std::vector &nums, std::string *err_msg) +{ + return je_ctl_get_all_arenas_num("muzzy_decay_ms", nums, err_msg); +} + +bool je_ctl_get_all_arenas_muzzy_decay_ms_info(std::string *info) +{ + return je_ctl_get_all_arenas_num_info("muzzy_decay_ms", info); +} + +bool je_ctl_decay_all_arenas(std::string *err_msg) +{ + const char *name = "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay"; + return je_ctl_set_void(name, err_msg); +} + +bool je_ctl_purge_all_arenas(std::string *err_msg) +{ + const char *name = "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge"; + return je_ctl_set_void(name, err_msg); +} + +static void je_stats_cb(void *opaque, const char *str) +{ + if (str == nullptr) { + return; + } + + ddebug_f("{}", str); + + auto stats = reinterpret_cast(opaque); + auto len = strlen(str); + if (stats->size() + len > stats->capacity()) { + return; + } + + stats->append(str); +} + +static void je_dump_malloc_stats(const char *opts, size_t max_bytes, std::string *stats) +{ + // Avoid malloc in callback + stats->reserve(max_bytes); + + ddebug_f(" malloc stats:"); + malloc_stats_print(je_stats_cb, stats, opts); +} + +void je_dump_configs(std::string *stats) { je_dump_malloc_stats("mdablxe", 4 * 1024, stats); } + +void je_dump_summary_stats(std::string *stats) +{ + je_dump_malloc_stats("gmdablxe", 2 * 1024, stats); +} + +void je_dump_brief_arena_stats(std::string *stats) +{ + je_dump_malloc_stats("gblxe", 1024 * 1024, stats); +} + +void je_dump_detailed_stats(std::string *stats) +{ + je_dump_malloc_stats("", 2 * 1024 * 1024, stats); +} + +} // namespace utils +} // namespace dsn + +#endif // DSN_USE_JEMALLOC diff --git a/src/utils/je_ctl.h b/src/utils/je_ctl.h new file mode 100644 index 0000000000..22ab44d0b4 --- /dev/null +++ b/src/utils/je_ctl.h @@ -0,0 +1,61 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma once + +#ifdef DSN_USE_JEMALLOC + +#include +#include +#include +#include +#include +#include + +namespace dsn { +namespace utils { + +void je_initialize(); + +bool je_ctl_set_all_arenas_dirty_decay_ms(ssize_t dirty_decay_ms, std::string *err_msg); + +bool je_ctl_get_all_arenas_dirty_decay_ms(std::vector &nums, std::string *err_msg); + +bool je_ctl_get_all_arenas_dirty_decay_ms_info(std::string *info); + +bool je_ctl_set_all_arenas_muzzy_decay_ms(ssize_t muzzy_decay_ms, std::string *err_msg); + +bool je_ctl_get_all_arenas_muzzy_decay_ms(std::vector &nums, std::string *err_msg); + +bool je_ctl_get_all_arenas_muzzy_decay_ms_info(std::string *info); + +bool je_ctl_decay_all_arenas(std::string *err_msg); + +bool je_ctl_purge_all_arenas(std::string *err_msg); + +void je_dump_configs(std::string *stats); + +void je_dump_summary_stats(std::string *stats); + +void je_dump_brief_arena_stats(std::string *stats); + +void je_dump_detailed_stats(std::string *stats); + +} // namespace utils +} // namespace dsn + +#endif // DSN_USE_JEMALLOC diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 05725bf194..d87b610b15 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -322,7 +322,7 @@ message(STATUS "USE_JEMALLOC = ${USE_JEMALLOC}") ExternalProject_Add(jemalloc URL https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 URL_MD5 3d41fbf006e6ebffd489bdb304d009ae - CONFIGURE_COMMAND ./configure --prefix=${TP_OUTPUT} --enable-cxx --enable-stats --enable-prof + CONFIGURE_COMMAND ./configure --prefix=${TP_OUTPUT} --enable-cxx --enable-stats --enable-prof --with-malloc-conf=background_thread:true,percpu_arena:percpu,dirty_decay_ms:10000,muzzy_decay_ms:10000 BUILD_COMMAND make INSTALL_COMMAND make install BUILD_IN_SOURCE 1 From c60b52e6d5dd0528e3e12f03d4af163c7c07df35 Mon Sep 17 00:00:00 2001 From: wangdan Date: Tue, 7 Sep 2021 19:50:40 +0800 Subject: [PATCH 3/6] feat: support jemalloc --- bin/dsn.cmake | 2 +- src/replica/replica_stub.cpp | 91 +++++++++++++++++++++++++++++++ src/replica/replica_stub.h | 6 +++ src/utils/je_ctl.cpp | 101 ++++++++++++++++++++++++++--------- src/utils/je_ctl.h | 12 +++++ thirdparty/CMakeLists.txt | 2 +- 6 files changed, 188 insertions(+), 26 deletions(-) diff --git a/bin/dsn.cmake b/bin/dsn.cmake index afd5305f68..56f3c42829 100644 --- a/bin/dsn.cmake +++ b/bin/dsn.cmake @@ -36,7 +36,7 @@ if(ENABLE_GPERF AND USE_JEMALLOC) endif() if(USE_JEMALLOC) - set(JEMALLOC_LIB_TYPE "STATIC") + set(JEMALLOC_LIB_TYPE "SHARED") endif() # ================================================================== # diff --git a/src/replica/replica_stub.cpp b/src/replica/replica_stub.cpp index a4736eac39..76d1719cd8 100644 --- a/src/replica/replica_stub.cpp +++ b/src/replica/replica_stub.cpp @@ -110,6 +110,13 @@ replica_stub::replica_stub(replica_state_subscriber subscriber /*= nullptr*/, _get_jemalloc_summary_stats_command = nullptr; _get_jemalloc_brief_arena_stats_command = nullptr; _get_jemalloc_detailed_stats_command = nullptr; + _activate_jemalloc_prof_command = nullptr; + _deactivate_jemalloc_prof_command = nullptr; + _dump_jemalloc_prof_command = nullptr; + _enable_jemalloc_prof_gdump_command = nullptr; + _disable_jemalloc_prof_gdump_command = nullptr; + _reset_jemalloc_prof_command = nullptr; + #endif _replica_state_subscriber = subscriber; _is_long_subscriber = is_long_subscriber; @@ -2525,6 +2532,78 @@ void replica_stub::register_ctrl_command() dsn::utils::je_dump_detailed_stats(&stats); return stats; }); + + _activate_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( + {"replica.activate-jemalloc-prof"}, + "replica.activate-jemalloc-prof - activate jemalloc prof", + "activate jemalloc prof", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_activate_prof(&msg); + return msg; + }); + + _deactivate_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( + {"replica.deactivate-jemalloc-prof"}, + "replica.deactivate-jemalloc-prof - deactivate jemalloc prof", + "deactivate jemalloc prof", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_deactivate_prof(&msg); + return msg; + }); + + _dump_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( + {"replica.dump-jemalloc-prof"}, + "replica.dump-jemalloc-prof [path]", + "dump jemalloc prof", + [](const std::vector &args) { + const char *path = nullptr; + if (!args.empty()) { + path = args[0].c_str(); + } + + std::string msg; + dsn::utils::je_ctl_dump_prof(path, &msg); + return msg; + }); + + _enable_jemalloc_prof_gdump_command = ::dsn::command_manager::instance().register_command( + {"replica.enable-jemalloc-prof-gdump"}, + "replica.enable-jemalloc-prof-gdump - enable prof gdump for jemalloc", + "enable prof gdump for jemalloc", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_enable_prof_gdump(&msg); + return msg; + }); + + _disable_jemalloc_prof_gdump_command = ::dsn::command_manager::instance().register_command( + {"replica.disable-jemalloc-prof-gdump"}, + "replica.disable-jemalloc-prof-gdump - disable prof gdump for jemalloc", + "disable prof gdump for jemalloc", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_disable_prof_gdump(&msg); + return msg; + }); + + _reset_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( + {"replica.reset-jemalloc-prof"}, + "replica.reset-jemalloc-prof [lg_sample]", + "reset jemalloc prof", + [](const std::vector &args) { + uint64_t lg_sample = 19; + if (!args.empty()) { + if (!dsn::buf2uint64(args[0], lg_sample)) { + return std::string("ERR: invalid arguments"); + } + } + + std::string msg; + dsn::utils::je_ctl_reset_prof(static_cast(lg_sample), &msg); + return msg; + }); #endif _max_concurrent_bulk_load_downloading_count_command = dsn::command_manager::instance().register_command( @@ -2696,6 +2775,12 @@ void replica_stub::close() UNREGISTER_VALID_HANDLER(_get_jemalloc_summary_stats_command); UNREGISTER_VALID_HANDLER(_get_jemalloc_brief_arena_stats_command); UNREGISTER_VALID_HANDLER(_get_jemalloc_detailed_stats_command); + UNREGISTER_VALID_HANDLER(_activate_jemalloc_prof_command); + UNREGISTER_VALID_HANDLER(_deactivate_jemalloc_prof_command); + UNREGISTER_VALID_HANDLER(_dump_jemalloc_prof_command); + UNREGISTER_VALID_HANDLER(_enable_jemalloc_prof_gdump_command); + UNREGISTER_VALID_HANDLER(_disable_jemalloc_prof_gdump_command); + UNREGISTER_VALID_HANDLER(_reset_jemalloc_prof_command); #endif UNREGISTER_VALID_HANDLER(_max_concurrent_bulk_load_downloading_count_command); @@ -2720,6 +2805,12 @@ void replica_stub::close() _get_jemalloc_summary_stats_command = nullptr; _get_jemalloc_brief_arena_stats_command = nullptr; _get_jemalloc_detailed_stats_command = nullptr; + _activate_jemalloc_prof_command = nullptr; + _deactivate_jemalloc_prof_command = nullptr; + _dump_jemalloc_prof_command = nullptr; + _enable_jemalloc_prof_gdump_command = nullptr; + _disable_jemalloc_prof_gdump_command = nullptr; + _reset_jemalloc_prof_command = nullptr; #endif _max_concurrent_bulk_load_downloading_count_command = nullptr; diff --git a/src/replica/replica_stub.h b/src/replica/replica_stub.h index c9feca784b..fcd3054c1a 100644 --- a/src/replica/replica_stub.h +++ b/src/replica/replica_stub.h @@ -384,6 +384,12 @@ class replica_stub : public serverlet, public ref_counter dsn_handle_t _get_jemalloc_summary_stats_command; dsn_handle_t _get_jemalloc_brief_arena_stats_command; dsn_handle_t _get_jemalloc_detailed_stats_command; + dsn_handle_t _activate_jemalloc_prof_command; + dsn_handle_t _deactivate_jemalloc_prof_command; + dsn_handle_t _dump_jemalloc_prof_command; + dsn_handle_t _enable_jemalloc_prof_gdump_command; + dsn_handle_t _disable_jemalloc_prof_gdump_command; + dsn_handle_t _reset_jemalloc_prof_command; #endif dsn_handle_t _max_concurrent_bulk_load_downloading_count_command; diff --git a/src/utils/je_ctl.cpp b/src/utils/je_ctl.cpp index f6909ec04c..96d4e0e992 100644 --- a/src/utils/je_ctl.cpp +++ b/src/utils/je_ctl.cpp @@ -50,73 +50,75 @@ static bool je_ctl_check_err(const char *action, int err, std::string *err_msg) } template -static bool je_ctl_check_set_err(const char *name, T val, int err, std::string *err_msg) +static inline bool je_ctl_check_set_err(const char *name, T val, int err, std::string *err_msg) { std::string action(fmt::format("set {} to {}", name, val)); return je_ctl_check_err(action.c_str(), err, err_msg); } template -static bool je_ctl_set_num(const char *name, T val, std::string *err_msg) +static inline bool je_ctl_set_num(const char *name, T val, std::string *err_msg) { int je_ret = mallctl(name, nullptr, nullptr, &val, sizeof(val)); return je_ctl_check_set_err(name, val, je_ret, err_msg); } -/* -static bool je_ctl_set_str(const char *name, const char *val, std::string *err_msg) +static inline bool je_ctl_set_str(const char *name, const char *val, std::string *err_msg) { - void *v = static_cast(const_cast(val)); - int je_ret = mallctl(name, nullptr, nullptr, v, sizeof(val)); - return je_ctl_check_set_err(name, val, je_ret, err_msg); + void *p = nullptr; + size_t sz = 0; + if (val != nullptr) { + p = static_cast(&val); + sz = sizeof(val); + } + + int je_ret = mallctl(name, nullptr, nullptr, p, sz); + return je_ctl_check_set_err(name, val == nullptr ? "nullptr" : val, je_ret, err_msg); } -*/ -static bool je_ctl_set_void(const char *name, std::string *err_msg) +static inline bool je_ctl_set_void(const char *name, std::string *err_msg) { int je_ret = mallctl(name, nullptr, nullptr, nullptr, 0); return je_ctl_check_err(name, je_ret, err_msg); } -static bool je_ctl_check_get_err(const char *name, int err, std::string *err_msg) +static inline bool je_ctl_check_get_err(const char *name, int err, std::string *err_msg) { std::string action(fmt::format("get {}", name)); return je_ctl_check_err(action.c_str(), err, err_msg); } template -static bool je_ctl_get_num(const char *name, T &val, std::string *err_msg) +static inline bool je_ctl_get_num(const char *name, T &val, std::string *err_msg) { - size_t size = sizeof(val); - int je_ret = mallctl(name, &val, &size, nullptr, 0); + size_t sz = sizeof(val); + int je_ret = mallctl(name, &val, &sz, nullptr, 0); return je_ctl_check_get_err(name, je_ret, err_msg); } -void je_initialize() -{ - bool enable_je_bg_thread = true; - je_ctl_set_num("background_thread", enable_je_bg_thread, nullptr); -} +void je_initialize() { je_ctl_set_num("background_thread", true, nullptr); } -static bool je_ctl_get_narenas(unsigned &narenas, std::string *err_msg) +static inline bool je_ctl_get_narenas(unsigned &narenas, std::string *err_msg) { return je_ctl_get_num("arenas.narenas", narenas, err_msg); } -static std::string build_arena_name(unsigned index, const char *sub_name) +static inline std::string build_arena_name(unsigned index, const char *sub_name) { return fmt::format("arena.{}.{}", index, sub_name); } template -static bool je_ctl_set_arena_num(unsigned index, const char *sub_name, T val, std::string *err_msg) +static inline bool +je_ctl_set_arena_num(unsigned index, const char *sub_name, T val, std::string *err_msg) { std::string name(build_arena_name(index, sub_name)); return je_ctl_set_num(name.c_str(), val, err_msg); } template -static bool je_ctl_get_arena_num(unsigned index, const char *sub_name, T &val, std::string *err_msg) +static inline bool +je_ctl_get_arena_num(unsigned index, const char *sub_name, T &val, std::string *err_msg) { std::string name(build_arena_name(index, sub_name)); return je_ctl_get_num(name.c_str(), val, err_msg); @@ -225,8 +227,6 @@ static void je_stats_cb(void *opaque, const char *str) return; } - ddebug_f("{}", str); - auto stats = reinterpret_cast(opaque); auto len = strlen(str); if (stats->size() + len > stats->capacity()) { @@ -262,6 +262,59 @@ void je_dump_detailed_stats(std::string *stats) je_dump_malloc_stats("", 2 * 1024 * 1024, stats); } +static inline bool je_ctl_get_prof(bool &prof, std::string *err_msg) +{ + return je_ctl_get_num("opt.prof", prof, err_msg); +} + +#define CHECK_IF_PROF(err_msg) \ + do { \ + bool prof = false; \ + if (!je_ctl_get_prof(prof, err_msg)) { \ + return false; \ + } \ + if (!prof) { \ + *err_msg = " prof is disabled now, enable it by " \ + "`export MALLOC_CONF=\"prof:true,prof_prefix:...\"`"; \ + return false; \ + } \ + } while (0) + +static inline bool je_ctl_set_prof_active(bool active, std::string *err_msg) +{ + CHECK_IF_PROF(err_msg); + return je_ctl_set_num("prof.active", active, err_msg); +} + +bool je_ctl_activate_prof(std::string *err_msg) { return je_ctl_set_prof_active(true, err_msg); } + +bool je_ctl_deactivate_prof(std::string *err_msg) { return je_ctl_set_prof_active(false, err_msg); } + +bool je_ctl_dump_prof(const char *path, std::string *err_msg) +{ + CHECK_IF_PROF(err_msg); + return je_ctl_set_str("prof.dump", path, err_msg); +} + +static inline bool je_ctl_set_prof_gdump(bool gdump, std::string *err_msg) +{ + CHECK_IF_PROF(err_msg); + return je_ctl_set_num("prof.gdump", gdump, err_msg); +} + +bool je_ctl_enable_prof_gdump(std::string *err_msg) { return je_ctl_set_prof_gdump(true, err_msg); } + +bool je_ctl_disable_prof_gdump(std::string *err_msg) +{ + return je_ctl_set_prof_gdump(false, err_msg); +} + +bool je_ctl_reset_prof(size_t lg_sample, std::string *err_msg) +{ + CHECK_IF_PROF(err_msg); + return je_ctl_set_num("prof.reset", lg_sample, err_msg); +} + } // namespace utils } // namespace dsn diff --git a/src/utils/je_ctl.h b/src/utils/je_ctl.h index 22ab44d0b4..765ef245fe 100644 --- a/src/utils/je_ctl.h +++ b/src/utils/je_ctl.h @@ -55,6 +55,18 @@ void je_dump_brief_arena_stats(std::string *stats); void je_dump_detailed_stats(std::string *stats); +bool je_ctl_activate_prof(std::string *err_msg); + +bool je_ctl_deactivate_prof(std::string *err_msg); + +bool je_ctl_dump_prof(const char *path, std::string *err_msg); + +bool je_ctl_enable_prof_gdump(std::string *err_msg); + +bool je_ctl_disable_prof_gdump(std::string *err_msg); + +bool je_ctl_reset_prof(size_t lg_sample, std::string *err_msg); + } // namespace utils } // namespace dsn diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index d87b610b15..3aeabd5089 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -322,7 +322,7 @@ message(STATUS "USE_JEMALLOC = ${USE_JEMALLOC}") ExternalProject_Add(jemalloc URL https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 URL_MD5 3d41fbf006e6ebffd489bdb304d009ae - CONFIGURE_COMMAND ./configure --prefix=${TP_OUTPUT} --enable-cxx --enable-stats --enable-prof --with-malloc-conf=background_thread:true,percpu_arena:percpu,dirty_decay_ms:10000,muzzy_decay_ms:10000 + CONFIGURE_COMMAND ./configure --prefix=${TP_OUTPUT} --enable-cxx --enable-stats --enable-prof --with-malloc-conf=background_thread:true,dirty_decay_ms:10000,muzzy_decay_ms:10000 BUILD_COMMAND make INSTALL_COMMAND make install BUILD_IN_SOURCE 1 From 96a43db4825f5c0d98799ccc6c250108983dff44 Mon Sep 17 00:00:00 2001 From: wangdan Date: Sun, 12 Sep 2021 22:25:09 +0800 Subject: [PATCH 4/6] feat: support jemalloc --- bin/dsn.cmake | 3 +- src/replica/replica_stub.cpp | 426 +++++++++++++++++++---------------- src/replica/replica_stub.h | 9 +- src/utils/je_ctl.cpp | 111 +++++++-- src/utils/je_ctl.h | 38 +++- 5 files changed, 364 insertions(+), 223 deletions(-) diff --git a/bin/dsn.cmake b/bin/dsn.cmake index 56f3c42829..7025b00875 100644 --- a/bin/dsn.cmake +++ b/bin/dsn.cmake @@ -284,7 +284,8 @@ function(dsn_setup_system_libs) if(USE_JEMALLOC) find_package(Jemalloc REQUIRED) - set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} JeMalloc::JeMalloc) + # also use cpu profiler provided by gperftools + set(DSN_SYSTEM_LIBS ${DSN_SYSTEM_LIBS} JeMalloc::JeMalloc profiler) add_definitions(-DDSN_USE_JEMALLOC) endif() diff --git a/src/replica/replica_stub.cpp b/src/replica/replica_stub.cpp index 76d1719cd8..a4b62f3087 100644 --- a/src/replica/replica_stub.cpp +++ b/src/replica/replica_stub.cpp @@ -102,10 +102,9 @@ replica_stub::replica_stub(replica_state_subscriber subscriber /*= nullptr*/, _max_reserved_memory_percentage_command = nullptr; _release_all_reserved_memory_command = nullptr; #elif defined(DSN_USE_JEMALLOC) - _set_jemalloc_all_arenas_dirty_decay_ms_command = nullptr; - _set_jemalloc_all_arenas_muzzy_decay_ms_command = nullptr; - _decay_jemalloc_all_arenas_command = nullptr; - _purge_jemalloc_all_arenas_command = nullptr; + _set_jemalloc_arena_dirty_decay_ms_command = nullptr; + _set_jemalloc_arena_muzzy_decay_ms_command = nullptr; + _gc_jemalloc_arena_command = nullptr; _get_jemalloc_configs_command = nullptr; _get_jemalloc_summary_stats_command = nullptr; _get_jemalloc_brief_arena_stats_command = nullptr; @@ -2272,6 +2271,229 @@ void replica_stub::open_service() register_ctrl_command(); } +#if !defined(DSN_ENABLE_GPERF) && defined(DSN_USE_JEMALLOC) +static std::string process_jemalloc_arena_decay_ms_command(const std::vector &args, + dsn::utils::je_decay_type decay_type) +{ + if (args.empty()) { + return std::string("ERR: invalid arguments"); + } + + bool all = false; + int32_t index = 0; + if (args[0] == "ALL") { + all = true; + } else if (!dsn::buf2int32(args[0], index)) { + return std::string("ERR: invalid arena index"); + } else if (index < 0) { + return std::string("ERR: invalid arena index"); + } + + if (args.size() < 2) { + // show current value + std::string info; + if (all) { + dsn::utils::je_ctl_get_all_arenas_decay_ms_info(decay_type, &info); + } else { + dsn::utils::je_ctl_get_arena_decay_ms_info( + static_cast(index), decay_type, &info); + } + return info; + } + + int64_t decay_ms = 0; + if (args[1] == "DEFAULT") { + // set to default value + decay_ms = 10000; + } else if (!dsn::buf2int64(args[1], decay_ms)) { + return std::string("ERR: invalid decay ms"); + } + + std::string msg; + if (all) { + dsn::utils::je_ctl_set_all_arenas_decay_ms( + decay_type, static_cast(decay_ms), &msg); + } else { + dsn::utils::je_ctl_set_arena_decay_ms( + static_cast(index), decay_type, static_cast(decay_ms), &msg); + } + return msg; +} + +static std::string process_jemalloc_gc_arena_command(const std::vector &args) +{ + if (args.empty() || args.size() < 2) { + return std::string("ERR: invalid arguments"); + } + + dsn::utils::je_gc_type gc_type; + if (args[0] == "decay") { + gc_type = dsn::utils::JE_DECAY_GC; + } else if (args[0] == "purge") { + gc_type = dsn::utils::JE_PURGE_GC; + } else { + return std::string("ERR: invalid gc type"); + } + + bool all = false; + int32_t index = 0; + if (args[1] == "ALL") { + all = true; + } else if (!dsn::buf2int32(args[1], index)) { + return std::string("ERR: invalid arena index"); + } else if (index < 0) { + return std::string("ERR: invalid arena index"); + } + + std::string msg; + if (all) { + dsn::utils::je_ctl_gc_all_arenas(gc_type, &msg); + } else { + dsn::utils::je_ctl_gc_arena(static_cast(index), gc_type, &msg); + } + return msg; +} + +void replica_stub::register_jemalloc_ctrl_command() +{ + _set_jemalloc_arena_dirty_decay_ms_command = + ::dsn::command_manager::instance().register_command( + {"replica.set-jemalloc-arena-dirty-decay-ms"}, + "replica.set-jemalloc-arena-dirty-decay-ms [decay_ms | DEFAULT]", + "set dirty decay ms for arena's memory of jemalloc", + [](const std::vector &args) { + return process_jemalloc_arena_decay_ms_command(args, dsn::utils::JE_DIRTY_DECAY); + }); + + _set_jemalloc_arena_muzzy_decay_ms_command = + ::dsn::command_manager::instance().register_command( + {"replica.set-jemalloc-arena-muzzy-decay-ms"}, + "replica.set-jemalloc-arena-muzzy-decay-ms [decay_ms | DEFAULT]", + "set muzzy decay ms for arena's memory of jemalloc", + [](const std::vector &args) { + return process_jemalloc_arena_decay_ms_command(args, dsn::utils::JE_MUZZY_DECAY); + }); + + _gc_jemalloc_arena_command = ::dsn::command_manager::instance().register_command( + {"replica.gc-jemalloc-arena"}, + "replica.gc-jemalloc-arena ", + "gc arena's memory of jemalloc", + process_jemalloc_gc_arena_command); + + _get_jemalloc_configs_command = ::dsn::command_manager::instance().register_command( + {"replica.get-jemalloc-configs"}, + "replica.get-jemalloc-configs - get configs of jemalloc", + "get configs of jemalloc", + [](const std::vector &args) { + std::string stats("\n"); + dsn::utils::je_dump_configs(&stats); + return stats; + }); + + _get_jemalloc_summary_stats_command = ::dsn::command_manager::instance().register_command( + {"replica.get-jemalloc-summary-stats"}, + "replica.get-jemalloc-summary-stats - get summary stats of jemalloc", + "get summary stats of jemalloc", + [](const std::vector &args) { + std::string stats("\n"); + dsn::utils::je_dump_summary_stats(&stats); + return stats; + }); + + _get_jemalloc_brief_arena_stats_command = ::dsn::command_manager::instance().register_command( + {"replica.get-jemalloc-brief-arena-stats"}, + "replica.get-jemalloc-brief-arena-stats - get brief_arena stats of jemalloc", + "get brief arena stats of jemalloc", + [](const std::vector &args) { + std::string stats("\n"); + dsn::utils::je_dump_brief_arena_stats(&stats); + return stats; + }); + + _get_jemalloc_detailed_stats_command = ::dsn::command_manager::instance().register_command( + {"replica.get-jemalloc-detailed-stats"}, + "replica.get-jemalloc-detailed-stats - get detailed stats of jemalloc", + "get detailed stats of jemalloc", + [](const std::vector &args) { + std::string stats("\n"); + dsn::utils::je_dump_detailed_stats(&stats); + return stats; + }); + + _activate_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( + {"replica.activate-jemalloc-prof"}, + "replica.activate-jemalloc-prof - activate jemalloc prof", + "activate jemalloc prof", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_activate_prof(&msg); + return msg; + }); + + _deactivate_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( + {"replica.deactivate-jemalloc-prof"}, + "replica.deactivate-jemalloc-prof - deactivate jemalloc prof", + "deactivate jemalloc prof", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_deactivate_prof(&msg); + return msg; + }); + + _dump_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( + {"replica.dump-jemalloc-prof"}, + "replica.dump-jemalloc-prof [path]", + "dump jemalloc prof", + [](const std::vector &args) { + const char *path = nullptr; + if (!args.empty()) { + path = args[0].c_str(); + } + + std::string msg; + dsn::utils::je_ctl_dump_prof(path, &msg); + return msg; + }); + + _enable_jemalloc_prof_gdump_command = ::dsn::command_manager::instance().register_command( + {"replica.enable-jemalloc-prof-gdump"}, + "replica.enable-jemalloc-prof-gdump - enable prof gdump for jemalloc", + "enable prof gdump for jemalloc", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_enable_prof_gdump(&msg); + return msg; + }); + + _disable_jemalloc_prof_gdump_command = ::dsn::command_manager::instance().register_command( + {"replica.disable-jemalloc-prof-gdump"}, + "replica.disable-jemalloc-prof-gdump - disable prof gdump for jemalloc", + "disable prof gdump for jemalloc", + [](const std::vector &args) { + std::string msg; + dsn::utils::je_ctl_disable_prof_gdump(&msg); + return msg; + }); + + _reset_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( + {"replica.reset-jemalloc-prof"}, + "replica.reset-jemalloc-prof [lg_sample]", + "reset jemalloc prof", + [](const std::vector &args) { + uint64_t lg_sample = 19; + if (!args.empty()) { + if (!dsn::buf2uint64(args[0], lg_sample)) { + return std::string("ERR: invalid arguments"); + } + } + + std::string msg; + dsn::utils::je_ctl_reset_prof(static_cast(lg_sample), &msg); + return msg; + }); +} +#endif + void replica_stub::register_ctrl_command() { /// In simple_kv test, three replica apps are created, which means that three replica_stubs are @@ -2423,187 +2645,7 @@ void replica_stub::register_ctrl_command() return "OK, release_bytes=" + std::to_string(release_bytes); }); #elif defined(DSN_USE_JEMALLOC) - _set_jemalloc_all_arenas_dirty_decay_ms_command = ::dsn::command_manager::instance().register_command( - {"replica.set-jemalloc-all-arenas-dirty-decay-ms"}, - "replica.set-jemalloc-all-arenas-dirty-decay-ms [num | DEFAULT]", - "set dirty decay ms for all arenas memory of jemalloc", - [](const std::vector &args) { - if (args.empty()) { - // show current value - std::string info; - dsn::utils::je_ctl_get_all_arenas_dirty_decay_ms_info(&info); - return info; - } - - int64_t dirty_decay_ms = 0; - if (args[0] == "DEFAULT") { - // set to default value - dirty_decay_ms = 10000; - } else if (!dsn::buf2int64(args[0], dirty_decay_ms)) { - return std::string("ERR: invalid arguments"); - } - - std::string msg; - dsn::utils::je_ctl_set_all_arenas_dirty_decay_ms(static_cast(dirty_decay_ms), &msg); - return msg; - }); - - _set_jemalloc_all_arenas_muzzy_decay_ms_command = ::dsn::command_manager::instance().register_command( - {"replica.set-jemalloc-all-arenas-muzzy-decay-ms"}, - "replica.set-jemalloc-all-arenas-muzzy-decay-ms [num | DEFAULT]", - "set muzzy decay ms for all arenas memory of jemalloc", - [](const std::vector &args) { - if (args.empty()) { - // show current value - std::string info; - dsn::utils::je_ctl_get_all_arenas_muzzy_decay_ms_info(&info); - return info; - } - - int64_t muzzy_decay_ms = 0; - if (args[0] == "DEFAULT") { - // set to default value - muzzy_decay_ms = 10000; - } else if (!dsn::buf2int64(args[0], muzzy_decay_ms)) { - return std::string("ERR: invalid arguments"); - } - - std::string msg; - dsn::utils::je_ctl_set_all_arenas_muzzy_decay_ms(static_cast(muzzy_decay_ms), &msg); - return msg; - }); - - _decay_jemalloc_all_arenas_command = ::dsn::command_manager::instance().register_command( - {"replica.decay-jemalloc-all-arenas"}, - "replica.decay-jemalloc-all-arenas - decay all arenas memory of jemalloc", - "decay all arenas memory of jemalloc", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_decay_all_arenas(&msg); - return msg; - }); - - _purge_jemalloc_all_arenas_command = ::dsn::command_manager::instance().register_command( - {"replica.purge-jemalloc-all-arenas"}, - "replica.purge-jemalloc-all-arenas - purge all arenas memory of jemalloc", - "purge all arenas memory of jemalloc", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_purge_all_arenas(&msg); - return msg; - }); - - _get_jemalloc_configs_command = ::dsn::command_manager::instance().register_command( - {"replica.get-jemalloc-configs"}, - "replica.get-jemalloc-configs - get configs of jemalloc", - "get configs of jemalloc", - [](const std::vector &args) { - std::string stats("\n"); - dsn::utils::je_dump_configs(&stats); - return stats; - }); - - _get_jemalloc_summary_stats_command = ::dsn::command_manager::instance().register_command( - {"replica.get-jemalloc-summary-stats"}, - "replica.get-jemalloc-summary-stats - get summary stats of jemalloc", - "get summary stats of jemalloc", - [](const std::vector &args) { - std::string stats("\n"); - dsn::utils::je_dump_summary_stats(&stats); - return stats; - }); - - _get_jemalloc_brief_arena_stats_command = ::dsn::command_manager::instance().register_command( - {"replica.get-jemalloc-brief-arena-stats"}, - "replica.get-jemalloc-brief-arena-stats - get brief_arena stats of jemalloc", - "get brief arena stats of jemalloc", - [](const std::vector &args) { - std::string stats("\n"); - dsn::utils::je_dump_brief_arena_stats(&stats); - return stats; - }); - - _get_jemalloc_detailed_stats_command = ::dsn::command_manager::instance().register_command( - {"replica.get-jemalloc-detailed-stats"}, - "replica.get-jemalloc-detailed-stats - get detailed stats of jemalloc", - "get detailed stats of jemalloc", - [](const std::vector &args) { - std::string stats("\n"); - dsn::utils::je_dump_detailed_stats(&stats); - return stats; - }); - - _activate_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( - {"replica.activate-jemalloc-prof"}, - "replica.activate-jemalloc-prof - activate jemalloc prof", - "activate jemalloc prof", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_activate_prof(&msg); - return msg; - }); - - _deactivate_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( - {"replica.deactivate-jemalloc-prof"}, - "replica.deactivate-jemalloc-prof - deactivate jemalloc prof", - "deactivate jemalloc prof", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_deactivate_prof(&msg); - return msg; - }); - - _dump_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( - {"replica.dump-jemalloc-prof"}, - "replica.dump-jemalloc-prof [path]", - "dump jemalloc prof", - [](const std::vector &args) { - const char *path = nullptr; - if (!args.empty()) { - path = args[0].c_str(); - } - - std::string msg; - dsn::utils::je_ctl_dump_prof(path, &msg); - return msg; - }); - - _enable_jemalloc_prof_gdump_command = ::dsn::command_manager::instance().register_command( - {"replica.enable-jemalloc-prof-gdump"}, - "replica.enable-jemalloc-prof-gdump - enable prof gdump for jemalloc", - "enable prof gdump for jemalloc", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_enable_prof_gdump(&msg); - return msg; - }); - - _disable_jemalloc_prof_gdump_command = ::dsn::command_manager::instance().register_command( - {"replica.disable-jemalloc-prof-gdump"}, - "replica.disable-jemalloc-prof-gdump - disable prof gdump for jemalloc", - "disable prof gdump for jemalloc", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_disable_prof_gdump(&msg); - return msg; - }); - - _reset_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( - {"replica.reset-jemalloc-prof"}, - "replica.reset-jemalloc-prof [lg_sample]", - "reset jemalloc prof", - [](const std::vector &args) { - uint64_t lg_sample = 19; - if (!args.empty()) { - if (!dsn::buf2uint64(args[0], lg_sample)) { - return std::string("ERR: invalid arguments"); - } - } - - std::string msg; - dsn::utils::je_ctl_reset_prof(static_cast(lg_sample), &msg); - return msg; - }); + register_jemalloc_ctrl_command(); #endif _max_concurrent_bulk_load_downloading_count_command = dsn::command_manager::instance().register_command( @@ -2767,10 +2809,9 @@ void replica_stub::close() UNREGISTER_VALID_HANDLER(_max_reserved_memory_percentage_command); UNREGISTER_VALID_HANDLER(_release_all_reserved_memory_command); #elif defined(DSN_USE_JEMALLOC) - UNREGISTER_VALID_HANDLER(_set_jemalloc_all_arenas_dirty_decay_ms_command); - UNREGISTER_VALID_HANDLER(_set_jemalloc_all_arenas_muzzy_decay_ms_command); - UNREGISTER_VALID_HANDLER(_decay_jemalloc_all_arenas_command); - UNREGISTER_VALID_HANDLER(_purge_jemalloc_all_arenas_command); + UNREGISTER_VALID_HANDLER(_set_jemalloc_arena_dirty_decay_ms_command); + UNREGISTER_VALID_HANDLER(_set_jemalloc_arena_muzzy_decay_ms_command); + UNREGISTER_VALID_HANDLER(_gc_jemalloc_arena_command); UNREGISTER_VALID_HANDLER(_get_jemalloc_configs_command); UNREGISTER_VALID_HANDLER(_get_jemalloc_summary_stats_command); UNREGISTER_VALID_HANDLER(_get_jemalloc_brief_arena_stats_command); @@ -2797,10 +2838,9 @@ void replica_stub::close() _max_reserved_memory_percentage_command = nullptr; _release_all_reserved_memory_command = nullptr; #elif defined(DSN_USE_JEMALLOC) - _set_jemalloc_all_arenas_dirty_decay_ms_command = nullptr; - _set_jemalloc_all_arenas_muzzy_decay_ms_command = nullptr; - _decay_jemalloc_all_arenas_command = nullptr; - _purge_jemalloc_all_arenas_command = nullptr; + _set_jemalloc_arena_dirty_decay_ms_command = nullptr; + _set_jemalloc_arena_muzzy_decay_ms_command = nullptr; + _gc_jemalloc_arena_command = nullptr; _get_jemalloc_configs_command = nullptr; _get_jemalloc_summary_stats_command = nullptr; _get_jemalloc_brief_arena_stats_command = nullptr; diff --git a/src/replica/replica_stub.h b/src/replica/replica_stub.h index fcd3054c1a..417cdf194f 100644 --- a/src/replica/replica_stub.h +++ b/src/replica/replica_stub.h @@ -304,6 +304,8 @@ class replica_stub : public serverlet, public ref_counter // Try to release tcmalloc memory back to operating system // If release_all = true, it will release all reserved-not-used memory uint64_t gc_tcmalloc_memory(bool release_all); +#elif defined(DSN_USE_JEMALLOC) + void register_jemalloc_ctrl_command(); #endif private: @@ -376,10 +378,9 @@ class replica_stub : public serverlet, public ref_counter dsn_handle_t _max_reserved_memory_percentage_command; dsn_handle_t _release_all_reserved_memory_command; #elif defined(DSN_USE_JEMALLOC) - dsn_handle_t _set_jemalloc_all_arenas_dirty_decay_ms_command; - dsn_handle_t _set_jemalloc_all_arenas_muzzy_decay_ms_command; - dsn_handle_t _decay_jemalloc_all_arenas_command; - dsn_handle_t _purge_jemalloc_all_arenas_command; + dsn_handle_t _set_jemalloc_arena_dirty_decay_ms_command; + dsn_handle_t _set_jemalloc_arena_muzzy_decay_ms_command; + dsn_handle_t _gc_jemalloc_arena_command; dsn_handle_t _get_jemalloc_configs_command; dsn_handle_t _get_jemalloc_summary_stats_command; dsn_handle_t _get_jemalloc_brief_arena_stats_command; diff --git a/src/utils/je_ctl.cpp b/src/utils/je_ctl.cpp index 96d4e0e992..07dadf4791 100644 --- a/src/utils/je_ctl.cpp +++ b/src/utils/je_ctl.cpp @@ -108,10 +108,25 @@ static inline std::string build_arena_name(unsigned index, const char *sub_name) return fmt::format("arena.{}.{}", index, sub_name); } +#define CHECK_ARENA_INDEX_OUT_OF_RANGE(index, err_msg) \ + do { \ + unsigned narenas = 0; \ + if (!je_ctl_get_narenas(narenas, err_msg)) { \ + return false; \ + } \ + if (index >= narenas) { \ + *err_msg = fmt::format( \ + " arena index out of range: index = {}, narenas = {}", index, narenas); \ + return false; \ + } \ + } while (0) + template static inline bool je_ctl_set_arena_num(unsigned index, const char *sub_name, T val, std::string *err_msg) { + CHECK_ARENA_INDEX_OUT_OF_RANGE(index, err_msg); + std::string name(build_arena_name(index, sub_name)); return je_ctl_set_num(name.c_str(), val, err_msg); } @@ -120,6 +135,8 @@ template static inline bool je_ctl_get_arena_num(unsigned index, const char *sub_name, T &val, std::string *err_msg) { + CHECK_ARENA_INDEX_OUT_OF_RANGE(index, err_msg); + std::string name(build_arena_name(index, sub_name)); return je_ctl_get_num(name.c_str(), val, err_msg); } @@ -165,6 +182,18 @@ je_ctl_get_all_arenas_num(const char *sub_name, std::vector &nums, std::strin return true; } +template +static bool je_ctl_get_arena_num_info(unsigned index, const char *sub_name, std::string *info) +{ + T num; + if (!je_ctl_get_arena_num(index, sub_name, num, info)) { + return false; + } + + info->append(fmt::format("\narena[{}]: {}", index, num)); + return true; +} + template static bool je_ctl_get_all_arenas_num_info(const char *sub_name, std::string *info) { @@ -179,45 +208,93 @@ static bool je_ctl_get_all_arenas_num_info(const char *sub_name, std::string *in return true; } -bool je_ctl_set_all_arenas_dirty_decay_ms(ssize_t dirty_decay_ms, std::string *err_msg) +static inline bool je_ctl_set_arena_void(unsigned index, const char *sub_name, std::string *err_msg) { - return je_ctl_set_all_arenas_num("dirty_decay_ms", dirty_decay_ms, err_msg); + CHECK_ARENA_INDEX_OUT_OF_RANGE(index, err_msg); + + std::string name(build_arena_name(index, sub_name)); + return je_ctl_set_void(name.c_str(), err_msg); } -bool je_ctl_get_all_arenas_dirty_decay_ms(std::vector &nums, std::string *err_msg) +static const char *je_decay_type_to_ms_name(je_decay_type type) { - return je_ctl_get_all_arenas_num("dirty_decay_ms", nums, err_msg); + static const char *name_map[] = { + "dirty_decay_ms", "muzzy_decay_ms", + }; + + dassert_f(type < sizeof(name_map) / sizeof(name_map[0]), "invalid je_decay_type: {}", type); + return name_map[type]; } -bool je_ctl_get_all_arenas_dirty_decay_ms_info(std::string *info) +bool je_ctl_set_arena_decay_ms(unsigned index, + je_decay_type decay_type, + ssize_t decay_ms, + std::string *err_msg) { - return je_ctl_get_all_arenas_num_info("dirty_decay_ms", info); + return je_ctl_set_arena_num(index, je_decay_type_to_ms_name(decay_type), decay_ms, err_msg); } -bool je_ctl_set_all_arenas_muzzy_decay_ms(ssize_t muzzy_decay_ms, std::string *err_msg) +bool je_ctl_set_all_arenas_decay_ms(je_decay_type decay_type, + ssize_t decay_ms, + std::string *err_msg) { - return je_ctl_set_all_arenas_num("muzzy_decay_ms", muzzy_decay_ms, err_msg); + return je_ctl_set_all_arenas_num(je_decay_type_to_ms_name(decay_type), decay_ms, err_msg); } -bool je_ctl_get_all_arenas_muzzy_decay_ms(std::vector &nums, std::string *err_msg) +bool je_ctl_get_arena_decay_ms(unsigned index, + je_decay_type decay_type, + ssize_t &decay_ms, + std::string *err_msg) { - return je_ctl_get_all_arenas_num("muzzy_decay_ms", nums, err_msg); + return je_ctl_get_arena_num(index, je_decay_type_to_ms_name(decay_type), decay_ms, err_msg); } -bool je_ctl_get_all_arenas_muzzy_decay_ms_info(std::string *info) +bool je_ctl_get_all_arenas_decay_ms(je_decay_type decay_type, + std::vector &decay_ms_list, + std::string *err_msg) { - return je_ctl_get_all_arenas_num_info("muzzy_decay_ms", info); + return je_ctl_get_all_arenas_num(je_decay_type_to_ms_name(decay_type), decay_ms_list, err_msg); } -bool je_ctl_decay_all_arenas(std::string *err_msg) +bool je_ctl_get_arena_decay_ms_info(unsigned index, je_decay_type decay_type, std::string *info) { - const char *name = "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay"; - return je_ctl_set_void(name, err_msg); + return je_ctl_get_arena_num_info(index, je_decay_type_to_ms_name(decay_type), info); +} + +bool je_ctl_get_all_arenas_decay_ms_info(je_decay_type decay_type, std::string *info) +{ + return je_ctl_get_all_arenas_num_info(je_decay_type_to_ms_name(decay_type), info); +} + +static const char *je_gc_type_to_name(je_gc_type type) +{ + static const char *name_map[] = { + "decay", "purge", + }; + + dassert_f(type < sizeof(name_map) / sizeof(name_map[0]), "invalid je_gc_type: {}", type); + return name_map[type]; +} + +bool je_ctl_gc_arena(unsigned index, je_gc_type gc_type, std::string *err_msg) +{ + return je_ctl_set_arena_void(index, je_gc_type_to_name(gc_type), err_msg); +} + +static const char *je_gc_type_to_all_arenas_full_name(je_gc_type type) +{ + static const char *name_map[] = { + "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", + "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", + }; + + dassert_f(type < sizeof(name_map) / sizeof(name_map[0]), "invalid je_gc_type: {}", type); + return name_map[type]; } -bool je_ctl_purge_all_arenas(std::string *err_msg) +bool je_ctl_gc_all_arenas(je_gc_type gc_type, std::string *err_msg) { - const char *name = "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge"; + const char *name = je_gc_type_to_all_arenas_full_name(gc_type); return je_ctl_set_void(name, err_msg); } diff --git a/src/utils/je_ctl.h b/src/utils/je_ctl.h index 765ef245fe..061021c207 100644 --- a/src/utils/je_ctl.h +++ b/src/utils/je_ctl.h @@ -31,21 +31,43 @@ namespace utils { void je_initialize(); -bool je_ctl_set_all_arenas_dirty_decay_ms(ssize_t dirty_decay_ms, std::string *err_msg); +enum je_decay_type +{ + JE_DIRTY_DECAY = 0, + JE_MUZZY_DECAY = 1, +}; -bool je_ctl_get_all_arenas_dirty_decay_ms(std::vector &nums, std::string *err_msg); +bool je_ctl_set_arena_decay_ms(unsigned index, + je_decay_type decay_type, + ssize_t decay_ms, + std::string *err_msg); -bool je_ctl_get_all_arenas_dirty_decay_ms_info(std::string *info); +bool je_ctl_set_all_arenas_decay_ms(je_decay_type decay_type, + ssize_t decay_ms, + std::string *err_msg); -bool je_ctl_set_all_arenas_muzzy_decay_ms(ssize_t muzzy_decay_ms, std::string *err_msg); +bool je_ctl_get_arena_decay_ms(unsigned index, + je_decay_type decay_type, + ssize_t &decay_ms, + std::string *err_msg); -bool je_ctl_get_all_arenas_muzzy_decay_ms(std::vector &nums, std::string *err_msg); +bool je_ctl_get_all_arenas_decay_ms(je_decay_type decay_type, + std::vector &decay_ms_list, + std::string *err_msg); -bool je_ctl_get_all_arenas_muzzy_decay_ms_info(std::string *info); +bool je_ctl_get_arena_decay_ms_info(unsigned index, je_decay_type decay_type, std::string *info); -bool je_ctl_decay_all_arenas(std::string *err_msg); +bool je_ctl_get_all_arenas_decay_ms_info(je_decay_type decay_type, std::string *info); -bool je_ctl_purge_all_arenas(std::string *err_msg); +enum je_gc_type +{ + JE_DECAY_GC = 0, + JE_PURGE_GC = 1, +}; + +bool je_ctl_gc_arena(unsigned index, je_gc_type gc_type, std::string *err_msg); + +bool je_ctl_gc_all_arenas(je_gc_type gc_type, std::string *err_msg); void je_dump_configs(std::string *stats); From ee133b105367ff93edaa38d710e61c5015bc6a92 Mon Sep 17 00:00:00 2001 From: wangdan Date: Mon, 13 Sep 2021 14:10:40 +0800 Subject: [PATCH 5/6] feat: support jemalloc --- src/utils/je_ctl.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/je_ctl.cpp b/src/utils/je_ctl.cpp index 07dadf4791..203c1dd6ed 100644 --- a/src/utils/je_ctl.cpp +++ b/src/utils/je_ctl.cpp @@ -318,7 +318,6 @@ static void je_dump_malloc_stats(const char *opts, size_t max_bytes, std::string // Avoid malloc in callback stats->reserve(max_bytes); - ddebug_f(" malloc stats:"); malloc_stats_print(je_stats_cb, stats, opts); } From cc599a0c578098fce7b84e33c96c2e3bb897c776 Mon Sep 17 00:00:00 2001 From: Dan Wang Date: Mon, 27 Sep 2021 15:03:43 +0800 Subject: [PATCH 6/6] feat: support jemalloc --- bin/FindJemalloc.cmake | 2 - bin/dsn.cmake | 3 - src/replica/replica_stub.cpp | 270 ----------------------- src/replica/replica_stub.h | 16 -- src/runtime/service_api_c.cpp | 6 - src/utils/je_ctl.cpp | 397 ---------------------------------- src/utils/je_ctl.h | 95 -------- thirdparty/CMakeLists.txt | 2 +- 8 files changed, 1 insertion(+), 790 deletions(-) delete mode 100644 src/utils/je_ctl.cpp delete mode 100644 src/utils/je_ctl.h diff --git a/bin/FindJemalloc.cmake b/bin/FindJemalloc.cmake index bc7c09c807..465f297d11 100644 --- a/bin/FindJemalloc.cmake +++ b/bin/FindJemalloc.cmake @@ -57,8 +57,6 @@ mark_as_advanced( Jemalloc_STATIC_LIBRARIES ) -# Reuse JeMalloc::JeMalloc from RocksDB::rocksdb -# as the only exposed target if(Jemalloc_FOUND AND NOT (TARGET JeMalloc::JeMalloc)) if("${JEMALLOC_LIB_TYPE}" STREQUAL "SHARED") add_library(JeMalloc::JeMalloc SHARED IMPORTED) diff --git a/bin/dsn.cmake b/bin/dsn.cmake index 7025b00875..a46fce6c9b 100644 --- a/bin/dsn.cmake +++ b/bin/dsn.cmake @@ -329,9 +329,6 @@ function(dsn_setup_thirdparty_libs) find_package(zstd) find_package(lz4) if(USE_JEMALLOC) - # expose JeMalloc::JeMalloc to whoever wants to link RocksDB::rocksdb - # set(JEMALLOC_ROOT_DIR ${TP_OUTPUT}) - # find_package(JeMalloc REQUIRED) find_package(Jemalloc REQUIRED) endif() find_package(RocksDB REQUIRED) diff --git a/src/replica/replica_stub.cpp b/src/replica/replica_stub.cpp index a4b62f3087..52e677ab72 100644 --- a/src/replica/replica_stub.cpp +++ b/src/replica/replica_stub.cpp @@ -57,8 +57,6 @@ #include #ifdef DSN_ENABLE_GPERF #include -#elif defined(DSN_USE_JEMALLOC) -#include "utils/je_ctl.h" #endif #include #include @@ -101,21 +99,6 @@ replica_stub::replica_stub(replica_state_subscriber subscriber /*= nullptr*/, _get_tcmalloc_status_command = nullptr; _max_reserved_memory_percentage_command = nullptr; _release_all_reserved_memory_command = nullptr; -#elif defined(DSN_USE_JEMALLOC) - _set_jemalloc_arena_dirty_decay_ms_command = nullptr; - _set_jemalloc_arena_muzzy_decay_ms_command = nullptr; - _gc_jemalloc_arena_command = nullptr; - _get_jemalloc_configs_command = nullptr; - _get_jemalloc_summary_stats_command = nullptr; - _get_jemalloc_brief_arena_stats_command = nullptr; - _get_jemalloc_detailed_stats_command = nullptr; - _activate_jemalloc_prof_command = nullptr; - _deactivate_jemalloc_prof_command = nullptr; - _dump_jemalloc_prof_command = nullptr; - _enable_jemalloc_prof_gdump_command = nullptr; - _disable_jemalloc_prof_gdump_command = nullptr; - _reset_jemalloc_prof_command = nullptr; - #endif _replica_state_subscriber = subscriber; _is_long_subscriber = is_long_subscriber; @@ -2271,229 +2254,6 @@ void replica_stub::open_service() register_ctrl_command(); } -#if !defined(DSN_ENABLE_GPERF) && defined(DSN_USE_JEMALLOC) -static std::string process_jemalloc_arena_decay_ms_command(const std::vector &args, - dsn::utils::je_decay_type decay_type) -{ - if (args.empty()) { - return std::string("ERR: invalid arguments"); - } - - bool all = false; - int32_t index = 0; - if (args[0] == "ALL") { - all = true; - } else if (!dsn::buf2int32(args[0], index)) { - return std::string("ERR: invalid arena index"); - } else if (index < 0) { - return std::string("ERR: invalid arena index"); - } - - if (args.size() < 2) { - // show current value - std::string info; - if (all) { - dsn::utils::je_ctl_get_all_arenas_decay_ms_info(decay_type, &info); - } else { - dsn::utils::je_ctl_get_arena_decay_ms_info( - static_cast(index), decay_type, &info); - } - return info; - } - - int64_t decay_ms = 0; - if (args[1] == "DEFAULT") { - // set to default value - decay_ms = 10000; - } else if (!dsn::buf2int64(args[1], decay_ms)) { - return std::string("ERR: invalid decay ms"); - } - - std::string msg; - if (all) { - dsn::utils::je_ctl_set_all_arenas_decay_ms( - decay_type, static_cast(decay_ms), &msg); - } else { - dsn::utils::je_ctl_set_arena_decay_ms( - static_cast(index), decay_type, static_cast(decay_ms), &msg); - } - return msg; -} - -static std::string process_jemalloc_gc_arena_command(const std::vector &args) -{ - if (args.empty() || args.size() < 2) { - return std::string("ERR: invalid arguments"); - } - - dsn::utils::je_gc_type gc_type; - if (args[0] == "decay") { - gc_type = dsn::utils::JE_DECAY_GC; - } else if (args[0] == "purge") { - gc_type = dsn::utils::JE_PURGE_GC; - } else { - return std::string("ERR: invalid gc type"); - } - - bool all = false; - int32_t index = 0; - if (args[1] == "ALL") { - all = true; - } else if (!dsn::buf2int32(args[1], index)) { - return std::string("ERR: invalid arena index"); - } else if (index < 0) { - return std::string("ERR: invalid arena index"); - } - - std::string msg; - if (all) { - dsn::utils::je_ctl_gc_all_arenas(gc_type, &msg); - } else { - dsn::utils::je_ctl_gc_arena(static_cast(index), gc_type, &msg); - } - return msg; -} - -void replica_stub::register_jemalloc_ctrl_command() -{ - _set_jemalloc_arena_dirty_decay_ms_command = - ::dsn::command_manager::instance().register_command( - {"replica.set-jemalloc-arena-dirty-decay-ms"}, - "replica.set-jemalloc-arena-dirty-decay-ms [decay_ms | DEFAULT]", - "set dirty decay ms for arena's memory of jemalloc", - [](const std::vector &args) { - return process_jemalloc_arena_decay_ms_command(args, dsn::utils::JE_DIRTY_DECAY); - }); - - _set_jemalloc_arena_muzzy_decay_ms_command = - ::dsn::command_manager::instance().register_command( - {"replica.set-jemalloc-arena-muzzy-decay-ms"}, - "replica.set-jemalloc-arena-muzzy-decay-ms [decay_ms | DEFAULT]", - "set muzzy decay ms for arena's memory of jemalloc", - [](const std::vector &args) { - return process_jemalloc_arena_decay_ms_command(args, dsn::utils::JE_MUZZY_DECAY); - }); - - _gc_jemalloc_arena_command = ::dsn::command_manager::instance().register_command( - {"replica.gc-jemalloc-arena"}, - "replica.gc-jemalloc-arena ", - "gc arena's memory of jemalloc", - process_jemalloc_gc_arena_command); - - _get_jemalloc_configs_command = ::dsn::command_manager::instance().register_command( - {"replica.get-jemalloc-configs"}, - "replica.get-jemalloc-configs - get configs of jemalloc", - "get configs of jemalloc", - [](const std::vector &args) { - std::string stats("\n"); - dsn::utils::je_dump_configs(&stats); - return stats; - }); - - _get_jemalloc_summary_stats_command = ::dsn::command_manager::instance().register_command( - {"replica.get-jemalloc-summary-stats"}, - "replica.get-jemalloc-summary-stats - get summary stats of jemalloc", - "get summary stats of jemalloc", - [](const std::vector &args) { - std::string stats("\n"); - dsn::utils::je_dump_summary_stats(&stats); - return stats; - }); - - _get_jemalloc_brief_arena_stats_command = ::dsn::command_manager::instance().register_command( - {"replica.get-jemalloc-brief-arena-stats"}, - "replica.get-jemalloc-brief-arena-stats - get brief_arena stats of jemalloc", - "get brief arena stats of jemalloc", - [](const std::vector &args) { - std::string stats("\n"); - dsn::utils::je_dump_brief_arena_stats(&stats); - return stats; - }); - - _get_jemalloc_detailed_stats_command = ::dsn::command_manager::instance().register_command( - {"replica.get-jemalloc-detailed-stats"}, - "replica.get-jemalloc-detailed-stats - get detailed stats of jemalloc", - "get detailed stats of jemalloc", - [](const std::vector &args) { - std::string stats("\n"); - dsn::utils::je_dump_detailed_stats(&stats); - return stats; - }); - - _activate_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( - {"replica.activate-jemalloc-prof"}, - "replica.activate-jemalloc-prof - activate jemalloc prof", - "activate jemalloc prof", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_activate_prof(&msg); - return msg; - }); - - _deactivate_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( - {"replica.deactivate-jemalloc-prof"}, - "replica.deactivate-jemalloc-prof - deactivate jemalloc prof", - "deactivate jemalloc prof", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_deactivate_prof(&msg); - return msg; - }); - - _dump_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( - {"replica.dump-jemalloc-prof"}, - "replica.dump-jemalloc-prof [path]", - "dump jemalloc prof", - [](const std::vector &args) { - const char *path = nullptr; - if (!args.empty()) { - path = args[0].c_str(); - } - - std::string msg; - dsn::utils::je_ctl_dump_prof(path, &msg); - return msg; - }); - - _enable_jemalloc_prof_gdump_command = ::dsn::command_manager::instance().register_command( - {"replica.enable-jemalloc-prof-gdump"}, - "replica.enable-jemalloc-prof-gdump - enable prof gdump for jemalloc", - "enable prof gdump for jemalloc", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_enable_prof_gdump(&msg); - return msg; - }); - - _disable_jemalloc_prof_gdump_command = ::dsn::command_manager::instance().register_command( - {"replica.disable-jemalloc-prof-gdump"}, - "replica.disable-jemalloc-prof-gdump - disable prof gdump for jemalloc", - "disable prof gdump for jemalloc", - [](const std::vector &args) { - std::string msg; - dsn::utils::je_ctl_disable_prof_gdump(&msg); - return msg; - }); - - _reset_jemalloc_prof_command = ::dsn::command_manager::instance().register_command( - {"replica.reset-jemalloc-prof"}, - "replica.reset-jemalloc-prof [lg_sample]", - "reset jemalloc prof", - [](const std::vector &args) { - uint64_t lg_sample = 19; - if (!args.empty()) { - if (!dsn::buf2uint64(args[0], lg_sample)) { - return std::string("ERR: invalid arguments"); - } - } - - std::string msg; - dsn::utils::je_ctl_reset_prof(static_cast(lg_sample), &msg); - return msg; - }); -} -#endif - void replica_stub::register_ctrl_command() { /// In simple_kv test, three replica apps are created, which means that three replica_stubs are @@ -2644,8 +2404,6 @@ void replica_stub::register_ctrl_command() auto release_bytes = gc_tcmalloc_memory(true); return "OK, release_bytes=" + std::to_string(release_bytes); }); -#elif defined(DSN_USE_JEMALLOC) - register_jemalloc_ctrl_command(); #endif _max_concurrent_bulk_load_downloading_count_command = dsn::command_manager::instance().register_command( @@ -2808,20 +2566,6 @@ void replica_stub::close() UNREGISTER_VALID_HANDLER(_get_tcmalloc_status_command); UNREGISTER_VALID_HANDLER(_max_reserved_memory_percentage_command); UNREGISTER_VALID_HANDLER(_release_all_reserved_memory_command); -#elif defined(DSN_USE_JEMALLOC) - UNREGISTER_VALID_HANDLER(_set_jemalloc_arena_dirty_decay_ms_command); - UNREGISTER_VALID_HANDLER(_set_jemalloc_arena_muzzy_decay_ms_command); - UNREGISTER_VALID_HANDLER(_gc_jemalloc_arena_command); - UNREGISTER_VALID_HANDLER(_get_jemalloc_configs_command); - UNREGISTER_VALID_HANDLER(_get_jemalloc_summary_stats_command); - UNREGISTER_VALID_HANDLER(_get_jemalloc_brief_arena_stats_command); - UNREGISTER_VALID_HANDLER(_get_jemalloc_detailed_stats_command); - UNREGISTER_VALID_HANDLER(_activate_jemalloc_prof_command); - UNREGISTER_VALID_HANDLER(_deactivate_jemalloc_prof_command); - UNREGISTER_VALID_HANDLER(_dump_jemalloc_prof_command); - UNREGISTER_VALID_HANDLER(_enable_jemalloc_prof_gdump_command); - UNREGISTER_VALID_HANDLER(_disable_jemalloc_prof_gdump_command); - UNREGISTER_VALID_HANDLER(_reset_jemalloc_prof_command); #endif UNREGISTER_VALID_HANDLER(_max_concurrent_bulk_load_downloading_count_command); @@ -2837,20 +2581,6 @@ void replica_stub::close() _get_tcmalloc_status_command = nullptr; _max_reserved_memory_percentage_command = nullptr; _release_all_reserved_memory_command = nullptr; -#elif defined(DSN_USE_JEMALLOC) - _set_jemalloc_arena_dirty_decay_ms_command = nullptr; - _set_jemalloc_arena_muzzy_decay_ms_command = nullptr; - _gc_jemalloc_arena_command = nullptr; - _get_jemalloc_configs_command = nullptr; - _get_jemalloc_summary_stats_command = nullptr; - _get_jemalloc_brief_arena_stats_command = nullptr; - _get_jemalloc_detailed_stats_command = nullptr; - _activate_jemalloc_prof_command = nullptr; - _deactivate_jemalloc_prof_command = nullptr; - _dump_jemalloc_prof_command = nullptr; - _enable_jemalloc_prof_gdump_command = nullptr; - _disable_jemalloc_prof_gdump_command = nullptr; - _reset_jemalloc_prof_command = nullptr; #endif _max_concurrent_bulk_load_downloading_count_command = nullptr; diff --git a/src/replica/replica_stub.h b/src/replica/replica_stub.h index 417cdf194f..3b93f325b2 100644 --- a/src/replica/replica_stub.h +++ b/src/replica/replica_stub.h @@ -304,8 +304,6 @@ class replica_stub : public serverlet, public ref_counter // Try to release tcmalloc memory back to operating system // If release_all = true, it will release all reserved-not-used memory uint64_t gc_tcmalloc_memory(bool release_all); -#elif defined(DSN_USE_JEMALLOC) - void register_jemalloc_ctrl_command(); #endif private: @@ -377,20 +375,6 @@ class replica_stub : public serverlet, public ref_counter dsn_handle_t _get_tcmalloc_status_command; dsn_handle_t _max_reserved_memory_percentage_command; dsn_handle_t _release_all_reserved_memory_command; -#elif defined(DSN_USE_JEMALLOC) - dsn_handle_t _set_jemalloc_arena_dirty_decay_ms_command; - dsn_handle_t _set_jemalloc_arena_muzzy_decay_ms_command; - dsn_handle_t _gc_jemalloc_arena_command; - dsn_handle_t _get_jemalloc_configs_command; - dsn_handle_t _get_jemalloc_summary_stats_command; - dsn_handle_t _get_jemalloc_brief_arena_stats_command; - dsn_handle_t _get_jemalloc_detailed_stats_command; - dsn_handle_t _activate_jemalloc_prof_command; - dsn_handle_t _deactivate_jemalloc_prof_command; - dsn_handle_t _dump_jemalloc_prof_command; - dsn_handle_t _enable_jemalloc_prof_gdump_command; - dsn_handle_t _disable_jemalloc_prof_gdump_command; - dsn_handle_t _reset_jemalloc_prof_command; #endif dsn_handle_t _max_concurrent_bulk_load_downloading_count_command; diff --git a/src/runtime/service_api_c.cpp b/src/runtime/service_api_c.cpp index f42e86c457..649af2611b 100644 --- a/src/runtime/service_api_c.cpp +++ b/src/runtime/service_api_c.cpp @@ -45,8 +45,6 @@ #ifdef DSN_ENABLE_GPERF #include -#elif defined(DSN_USE_JEMALLOC) -#include "utils/je_ctl.h" #endif #include "service_engine.h" @@ -441,10 +439,6 @@ bool run(const char *config_file, // init logging dsn_log_init(spec.logging_factory_name, spec.dir_log, dsn_log_prefixed_message_func); -#if !defined(DSN_ENABLE_GPERF) && defined(DSN_USE_JEMALLOC) - dsn::utils::je_initialize(); -#endif - // prepare minimum necessary ::dsn::service_engine::instance().init_before_toollets(spec); diff --git a/src/utils/je_ctl.cpp b/src/utils/je_ctl.cpp deleted file mode 100644 index 203c1dd6ed..0000000000 --- a/src/utils/je_ctl.cpp +++ /dev/null @@ -1,397 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -#ifdef DSN_USE_JEMALLOC - -#include "je_ctl.h" - -#include -#include -#include -#include - -#define STRINGIFY_HELPER(x) #x -#define STRINGIFY(x) STRINGIFY_HELPER(x) - -namespace dsn { -namespace utils { - -static bool je_ctl_check_err(const char *action, int err, std::string *err_msg) -{ - std::string msg; - if (dsn_likely(err == 0)) { - msg = fmt::format("{} successfully", action); - } else { - msg = fmt::format( - "failed to {}: errno={}, message={}", action, err, dsn::utils::safe_strerror(err)); - } - - ddebug_f(" {}", msg); - - if (err_msg != nullptr) { - *err_msg = std::move(msg); - } - - return err == 0; -} - -template -static inline bool je_ctl_check_set_err(const char *name, T val, int err, std::string *err_msg) -{ - std::string action(fmt::format("set {} to {}", name, val)); - return je_ctl_check_err(action.c_str(), err, err_msg); -} - -template -static inline bool je_ctl_set_num(const char *name, T val, std::string *err_msg) -{ - int je_ret = mallctl(name, nullptr, nullptr, &val, sizeof(val)); - return je_ctl_check_set_err(name, val, je_ret, err_msg); -} - -static inline bool je_ctl_set_str(const char *name, const char *val, std::string *err_msg) -{ - void *p = nullptr; - size_t sz = 0; - if (val != nullptr) { - p = static_cast(&val); - sz = sizeof(val); - } - - int je_ret = mallctl(name, nullptr, nullptr, p, sz); - return je_ctl_check_set_err(name, val == nullptr ? "nullptr" : val, je_ret, err_msg); -} - -static inline bool je_ctl_set_void(const char *name, std::string *err_msg) -{ - int je_ret = mallctl(name, nullptr, nullptr, nullptr, 0); - return je_ctl_check_err(name, je_ret, err_msg); -} - -static inline bool je_ctl_check_get_err(const char *name, int err, std::string *err_msg) -{ - std::string action(fmt::format("get {}", name)); - return je_ctl_check_err(action.c_str(), err, err_msg); -} - -template -static inline bool je_ctl_get_num(const char *name, T &val, std::string *err_msg) -{ - size_t sz = sizeof(val); - int je_ret = mallctl(name, &val, &sz, nullptr, 0); - return je_ctl_check_get_err(name, je_ret, err_msg); -} - -void je_initialize() { je_ctl_set_num("background_thread", true, nullptr); } - -static inline bool je_ctl_get_narenas(unsigned &narenas, std::string *err_msg) -{ - return je_ctl_get_num("arenas.narenas", narenas, err_msg); -} - -static inline std::string build_arena_name(unsigned index, const char *sub_name) -{ - return fmt::format("arena.{}.{}", index, sub_name); -} - -#define CHECK_ARENA_INDEX_OUT_OF_RANGE(index, err_msg) \ - do { \ - unsigned narenas = 0; \ - if (!je_ctl_get_narenas(narenas, err_msg)) { \ - return false; \ - } \ - if (index >= narenas) { \ - *err_msg = fmt::format( \ - " arena index out of range: index = {}, narenas = {}", index, narenas); \ - return false; \ - } \ - } while (0) - -template -static inline bool -je_ctl_set_arena_num(unsigned index, const char *sub_name, T val, std::string *err_msg) -{ - CHECK_ARENA_INDEX_OUT_OF_RANGE(index, err_msg); - - std::string name(build_arena_name(index, sub_name)); - return je_ctl_set_num(name.c_str(), val, err_msg); -} - -template -static inline bool -je_ctl_get_arena_num(unsigned index, const char *sub_name, T &val, std::string *err_msg) -{ - CHECK_ARENA_INDEX_OUT_OF_RANGE(index, err_msg); - - std::string name(build_arena_name(index, sub_name)); - return je_ctl_get_num(name.c_str(), val, err_msg); -} - -template -static bool je_ctl_set_all_arenas_num(const char *sub_name, T val, std::string *err_msg) -{ - unsigned narenas = 0; - if (!je_ctl_get_narenas(narenas, err_msg)) { - return false; - } - - for (unsigned i = 0; i < narenas; ++i) { - if (!je_ctl_set_arena_num(i, sub_name, val, err_msg)) { - return false; - } - } - - *err_msg = fmt::format("set {} for all arenas successfully", sub_name); - return true; -} - -template -static bool -je_ctl_get_all_arenas_num(const char *sub_name, std::vector &nums, std::string *err_msg) -{ - unsigned narenas = 0; - if (!je_ctl_get_narenas(narenas, err_msg)) { - return false; - } - - nums.clear(); - nums.reserve(narenas); - for (unsigned i = 0; i < narenas; ++i) { - T val; - if (!je_ctl_get_arena_num(i, sub_name, val, err_msg)) { - return false; - } - nums.push_back(val); - } - - *err_msg = fmt::format("get {} for all arenas successfully", sub_name); - return true; -} - -template -static bool je_ctl_get_arena_num_info(unsigned index, const char *sub_name, std::string *info) -{ - T num; - if (!je_ctl_get_arena_num(index, sub_name, num, info)) { - return false; - } - - info->append(fmt::format("\narena[{}]: {}", index, num)); - return true; -} - -template -static bool je_ctl_get_all_arenas_num_info(const char *sub_name, std::string *info) -{ - std::vector nums; - if (!je_ctl_get_all_arenas_num(sub_name, nums, info)) { - return false; - } - - for (size_t i = 0; i < nums.size(); ++i) { - info->append(fmt::format("\narena[{}]: {}", i, nums[i])); - } - return true; -} - -static inline bool je_ctl_set_arena_void(unsigned index, const char *sub_name, std::string *err_msg) -{ - CHECK_ARENA_INDEX_OUT_OF_RANGE(index, err_msg); - - std::string name(build_arena_name(index, sub_name)); - return je_ctl_set_void(name.c_str(), err_msg); -} - -static const char *je_decay_type_to_ms_name(je_decay_type type) -{ - static const char *name_map[] = { - "dirty_decay_ms", "muzzy_decay_ms", - }; - - dassert_f(type < sizeof(name_map) / sizeof(name_map[0]), "invalid je_decay_type: {}", type); - return name_map[type]; -} - -bool je_ctl_set_arena_decay_ms(unsigned index, - je_decay_type decay_type, - ssize_t decay_ms, - std::string *err_msg) -{ - return je_ctl_set_arena_num(index, je_decay_type_to_ms_name(decay_type), decay_ms, err_msg); -} - -bool je_ctl_set_all_arenas_decay_ms(je_decay_type decay_type, - ssize_t decay_ms, - std::string *err_msg) -{ - return je_ctl_set_all_arenas_num(je_decay_type_to_ms_name(decay_type), decay_ms, err_msg); -} - -bool je_ctl_get_arena_decay_ms(unsigned index, - je_decay_type decay_type, - ssize_t &decay_ms, - std::string *err_msg) -{ - return je_ctl_get_arena_num(index, je_decay_type_to_ms_name(decay_type), decay_ms, err_msg); -} - -bool je_ctl_get_all_arenas_decay_ms(je_decay_type decay_type, - std::vector &decay_ms_list, - std::string *err_msg) -{ - return je_ctl_get_all_arenas_num(je_decay_type_to_ms_name(decay_type), decay_ms_list, err_msg); -} - -bool je_ctl_get_arena_decay_ms_info(unsigned index, je_decay_type decay_type, std::string *info) -{ - return je_ctl_get_arena_num_info(index, je_decay_type_to_ms_name(decay_type), info); -} - -bool je_ctl_get_all_arenas_decay_ms_info(je_decay_type decay_type, std::string *info) -{ - return je_ctl_get_all_arenas_num_info(je_decay_type_to_ms_name(decay_type), info); -} - -static const char *je_gc_type_to_name(je_gc_type type) -{ - static const char *name_map[] = { - "decay", "purge", - }; - - dassert_f(type < sizeof(name_map) / sizeof(name_map[0]), "invalid je_gc_type: {}", type); - return name_map[type]; -} - -bool je_ctl_gc_arena(unsigned index, je_gc_type gc_type, std::string *err_msg) -{ - return je_ctl_set_arena_void(index, je_gc_type_to_name(gc_type), err_msg); -} - -static const char *je_gc_type_to_all_arenas_full_name(je_gc_type type) -{ - static const char *name_map[] = { - "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay", - "arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", - }; - - dassert_f(type < sizeof(name_map) / sizeof(name_map[0]), "invalid je_gc_type: {}", type); - return name_map[type]; -} - -bool je_ctl_gc_all_arenas(je_gc_type gc_type, std::string *err_msg) -{ - const char *name = je_gc_type_to_all_arenas_full_name(gc_type); - return je_ctl_set_void(name, err_msg); -} - -static void je_stats_cb(void *opaque, const char *str) -{ - if (str == nullptr) { - return; - } - - auto stats = reinterpret_cast(opaque); - auto len = strlen(str); - if (stats->size() + len > stats->capacity()) { - return; - } - - stats->append(str); -} - -static void je_dump_malloc_stats(const char *opts, size_t max_bytes, std::string *stats) -{ - // Avoid malloc in callback - stats->reserve(max_bytes); - - malloc_stats_print(je_stats_cb, stats, opts); -} - -void je_dump_configs(std::string *stats) { je_dump_malloc_stats("mdablxe", 4 * 1024, stats); } - -void je_dump_summary_stats(std::string *stats) -{ - je_dump_malloc_stats("gmdablxe", 2 * 1024, stats); -} - -void je_dump_brief_arena_stats(std::string *stats) -{ - je_dump_malloc_stats("gblxe", 1024 * 1024, stats); -} - -void je_dump_detailed_stats(std::string *stats) -{ - je_dump_malloc_stats("", 2 * 1024 * 1024, stats); -} - -static inline bool je_ctl_get_prof(bool &prof, std::string *err_msg) -{ - return je_ctl_get_num("opt.prof", prof, err_msg); -} - -#define CHECK_IF_PROF(err_msg) \ - do { \ - bool prof = false; \ - if (!je_ctl_get_prof(prof, err_msg)) { \ - return false; \ - } \ - if (!prof) { \ - *err_msg = " prof is disabled now, enable it by " \ - "`export MALLOC_CONF=\"prof:true,prof_prefix:...\"`"; \ - return false; \ - } \ - } while (0) - -static inline bool je_ctl_set_prof_active(bool active, std::string *err_msg) -{ - CHECK_IF_PROF(err_msg); - return je_ctl_set_num("prof.active", active, err_msg); -} - -bool je_ctl_activate_prof(std::string *err_msg) { return je_ctl_set_prof_active(true, err_msg); } - -bool je_ctl_deactivate_prof(std::string *err_msg) { return je_ctl_set_prof_active(false, err_msg); } - -bool je_ctl_dump_prof(const char *path, std::string *err_msg) -{ - CHECK_IF_PROF(err_msg); - return je_ctl_set_str("prof.dump", path, err_msg); -} - -static inline bool je_ctl_set_prof_gdump(bool gdump, std::string *err_msg) -{ - CHECK_IF_PROF(err_msg); - return je_ctl_set_num("prof.gdump", gdump, err_msg); -} - -bool je_ctl_enable_prof_gdump(std::string *err_msg) { return je_ctl_set_prof_gdump(true, err_msg); } - -bool je_ctl_disable_prof_gdump(std::string *err_msg) -{ - return je_ctl_set_prof_gdump(false, err_msg); -} - -bool je_ctl_reset_prof(size_t lg_sample, std::string *err_msg) -{ - CHECK_IF_PROF(err_msg); - return je_ctl_set_num("prof.reset", lg_sample, err_msg); -} - -} // namespace utils -} // namespace dsn - -#endif // DSN_USE_JEMALLOC diff --git a/src/utils/je_ctl.h b/src/utils/je_ctl.h deleted file mode 100644 index 061021c207..0000000000 --- a/src/utils/je_ctl.h +++ /dev/null @@ -1,95 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -#pragma once - -#ifdef DSN_USE_JEMALLOC - -#include -#include -#include -#include -#include -#include - -namespace dsn { -namespace utils { - -void je_initialize(); - -enum je_decay_type -{ - JE_DIRTY_DECAY = 0, - JE_MUZZY_DECAY = 1, -}; - -bool je_ctl_set_arena_decay_ms(unsigned index, - je_decay_type decay_type, - ssize_t decay_ms, - std::string *err_msg); - -bool je_ctl_set_all_arenas_decay_ms(je_decay_type decay_type, - ssize_t decay_ms, - std::string *err_msg); - -bool je_ctl_get_arena_decay_ms(unsigned index, - je_decay_type decay_type, - ssize_t &decay_ms, - std::string *err_msg); - -bool je_ctl_get_all_arenas_decay_ms(je_decay_type decay_type, - std::vector &decay_ms_list, - std::string *err_msg); - -bool je_ctl_get_arena_decay_ms_info(unsigned index, je_decay_type decay_type, std::string *info); - -bool je_ctl_get_all_arenas_decay_ms_info(je_decay_type decay_type, std::string *info); - -enum je_gc_type -{ - JE_DECAY_GC = 0, - JE_PURGE_GC = 1, -}; - -bool je_ctl_gc_arena(unsigned index, je_gc_type gc_type, std::string *err_msg); - -bool je_ctl_gc_all_arenas(je_gc_type gc_type, std::string *err_msg); - -void je_dump_configs(std::string *stats); - -void je_dump_summary_stats(std::string *stats); - -void je_dump_brief_arena_stats(std::string *stats); - -void je_dump_detailed_stats(std::string *stats); - -bool je_ctl_activate_prof(std::string *err_msg); - -bool je_ctl_deactivate_prof(std::string *err_msg); - -bool je_ctl_dump_prof(const char *path, std::string *err_msg); - -bool je_ctl_enable_prof_gdump(std::string *err_msg); - -bool je_ctl_disable_prof_gdump(std::string *err_msg); - -bool je_ctl_reset_prof(size_t lg_sample, std::string *err_msg); - -} // namespace utils -} // namespace dsn - -#endif // DSN_USE_JEMALLOC diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 3aeabd5089..05725bf194 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -322,7 +322,7 @@ message(STATUS "USE_JEMALLOC = ${USE_JEMALLOC}") ExternalProject_Add(jemalloc URL https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 URL_MD5 3d41fbf006e6ebffd489bdb304d009ae - CONFIGURE_COMMAND ./configure --prefix=${TP_OUTPUT} --enable-cxx --enable-stats --enable-prof --with-malloc-conf=background_thread:true,dirty_decay_ms:10000,muzzy_decay_ms:10000 + CONFIGURE_COMMAND ./configure --prefix=${TP_OUTPUT} --enable-cxx --enable-stats --enable-prof BUILD_COMMAND make INSTALL_COMMAND make install BUILD_IN_SOURCE 1