mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-19 16:20:50 +00:00
Merge pull request #58665 from ClickHouse/jemalloc-system-commands
Add SYSTEM commands and Keeper 4LW for jemalloc
This commit is contained in:
commit
654fee820e
@ -95,6 +95,7 @@ if (BUILD_STANDALONE_KEEPER)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Common/CurrentThread.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Common/NamedCollections/NamedCollections.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Common/NamedCollections/NamedCollectionConfiguration.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Common/Jemalloc.cpp
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Common/ZooKeeper/IKeeper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/Common/ZooKeeper/TestKeeper.cpp
|
||||
|
@ -200,6 +200,7 @@ enum class AccessType
|
||||
M(SYSTEM_UNFREEZE, "SYSTEM UNFREEZE", GLOBAL, SYSTEM) \
|
||||
M(SYSTEM_FAILPOINT, "SYSTEM ENABLE FAILPOINT, SYSTEM DISABLE FAILPOINT", GLOBAL, SYSTEM) \
|
||||
M(SYSTEM_LISTEN, "SYSTEM START LISTEN, SYSTEM STOP LISTEN", GLOBAL, SYSTEM) \
|
||||
M(SYSTEM_JEMALLOC, "SYSTEM JEMALLOC PURGE, SYSTEM JEMALLOC ENABLE PROFILE, SYSTEM JEMALLOC DISABLE PROFILE, SYSTEM JEMALLOC FLUSH PROFILE", GLOBAL, SYSTEM) \
|
||||
M(SYSTEM, "", GROUP, ALL) /* allows to execute SYSTEM {SHUTDOWN|RELOAD CONFIG|...} */ \
|
||||
\
|
||||
M(dictGet, "dictHas, dictGetHierarchy, dictIsIn", DICTIONARY, ALL) /* allows to execute functions dictGet(), dictHas(), dictGetHierarchy(), dictIsIn() */\
|
||||
|
88
src/Common/Jemalloc.cpp
Normal file
88
src/Common/Jemalloc.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include <Common/Jemalloc.h>
|
||||
|
||||
#if USE_JEMALLOC
|
||||
|
||||
#include <Common/Stopwatch.h>
|
||||
#include <Common/logger_useful.h>
|
||||
#include <jemalloc/jemalloc.h>
|
||||
|
||||
#define STRINGIFY_HELPER(x) #x
|
||||
#define STRINGIFY(x) STRINGIFY_HELPER(x)
|
||||
|
||||
namespace ProfileEvents
|
||||
{
|
||||
extern const Event MemoryAllocatorPurge;
|
||||
extern const Event MemoryAllocatorPurgeTimeMicroseconds;
|
||||
}
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
void purgeJemallocArenas()
|
||||
{
|
||||
LOG_TRACE(&Poco::Logger::get("SystemJemalloc"), "Purging unused memory");
|
||||
Stopwatch watch;
|
||||
mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", nullptr, nullptr, nullptr, 0);
|
||||
ProfileEvents::increment(ProfileEvents::MemoryAllocatorPurge);
|
||||
ProfileEvents::increment(ProfileEvents::MemoryAllocatorPurgeTimeMicroseconds, watch.elapsedMicroseconds());
|
||||
}
|
||||
|
||||
void checkJemallocProfilingEnabled()
|
||||
{
|
||||
bool active = true;
|
||||
size_t active_size = sizeof(active);
|
||||
mallctl("opt.prof", &active, &active_size, nullptr, 0);
|
||||
|
||||
if (!active)
|
||||
throw Exception(
|
||||
ErrorCodes::BAD_ARGUMENTS,
|
||||
"ClickHouse was started without enabling profiling for jemalloc. To use jemalloc's profiler, following env variable should be "
|
||||
"set: MALLOC_CONF=background_thread:true,prof:true");
|
||||
}
|
||||
|
||||
void setJemallocProfileActive(bool value)
|
||||
{
|
||||
checkJemallocProfilingEnabled();
|
||||
bool active = true;
|
||||
size_t active_size = sizeof(active);
|
||||
mallctl("prof.active", &active, &active_size, nullptr, 0);
|
||||
if (active == value)
|
||||
{
|
||||
LOG_TRACE(&Poco::Logger::get("SystemJemalloc"), "Profiling is already {}", active ? "enabled" : "disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
mallctl("prof.active", nullptr, nullptr, &value, sizeof(bool));
|
||||
LOG_TRACE(&Poco::Logger::get("SystemJemalloc"), "Profiling is {}", value ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
std::string flushJemallocProfile(const std::string & file_prefix)
|
||||
{
|
||||
checkJemallocProfilingEnabled();
|
||||
char * prefix_buffer;
|
||||
size_t prefix_size = sizeof(prefix_buffer);
|
||||
int n = mallctl("opt.prof_prefix", &prefix_buffer, &prefix_size, nullptr, 0);
|
||||
if (!n && std::string_view(prefix_buffer) != "jeprof")
|
||||
{
|
||||
LOG_TRACE(&Poco::Logger::get("SystemJemalloc"), "Flushing memory profile with prefix {}", prefix_buffer);
|
||||
mallctl("prof.dump", nullptr, nullptr, nullptr, 0);
|
||||
return prefix_buffer;
|
||||
}
|
||||
|
||||
static std::atomic<size_t> profile_counter{0};
|
||||
std::string profile_dump_path = fmt::format("{}.{}.{}.heap", file_prefix, getpid(), profile_counter.fetch_add(1));
|
||||
const auto * profile_dump_path_str = profile_dump_path.c_str();
|
||||
|
||||
LOG_TRACE(&Poco::Logger::get("SystemJemalloc"), "Flushing memory profile to {}", profile_dump_path_str);
|
||||
mallctl("prof.dump", nullptr, nullptr, &profile_dump_path_str, sizeof(profile_dump_path_str));
|
||||
return profile_dump_path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
22
src/Common/Jemalloc.h
Normal file
22
src/Common/Jemalloc.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if USE_JEMALLOC
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
void purgeJemallocArenas();
|
||||
|
||||
void checkJemallocProfilingEnabled();
|
||||
|
||||
void setJemallocProfileActive(bool value);
|
||||
|
||||
std::string flushJemallocProfile(const std::string & file_prefix);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,10 +1,11 @@
|
||||
#include <Coordination/CoordinationSettings.h>
|
||||
#include <Common/logger_useful.h>
|
||||
#include <filesystem>
|
||||
#include <Coordination/Defines.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <IO/WriteIntText.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
@ -36,7 +37,11 @@ void CoordinationSettings::loadFromConfig(const String & config_elem, const Poco
|
||||
}
|
||||
|
||||
|
||||
const String KeeperConfigurationAndSettings::DEFAULT_FOUR_LETTER_WORD_CMD = "conf,cons,crst,envi,ruok,srst,srvr,stat,wchs,dirs,mntr,isro,rcvr,apiv,csnp,lgif,rqld,rclc,clrs,ftfl,ydld";
|
||||
const String KeeperConfigurationAndSettings::DEFAULT_FOUR_LETTER_WORD_CMD =
|
||||
#if USE_JEMALLOC
|
||||
"jmst,jmfp,jmep,jmdp,"
|
||||
#endif
|
||||
"conf,cons,crst,envi,ruok,srst,srvr,stat,wchs,dirs,mntr,isro,rcvr,apiv,csnp,lgif,rqld,rclc,clrs,ftfl,ydld";
|
||||
|
||||
KeeperConfigurationAndSettings::KeeperConfigurationAndSettings()
|
||||
: server_id(NOT_EXIST)
|
||||
|
@ -18,6 +18,11 @@
|
||||
#include <unistd.h>
|
||||
#include <bit>
|
||||
|
||||
#if USE_JEMALLOC
|
||||
#include <Common/Jemalloc.h>
|
||||
#include <jemalloc/jemalloc.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -175,6 +180,20 @@ void FourLetterCommandFactory::registerCommands(KeeperDispatcher & keeper_dispat
|
||||
FourLetterCommandPtr yield_leadership_command = std::make_shared<YieldLeadershipCommand>(keeper_dispatcher);
|
||||
factory.registerCommand(yield_leadership_command);
|
||||
|
||||
#if USE_JEMALLOC
|
||||
FourLetterCommandPtr jemalloc_dump_stats = std::make_shared<JemallocDumpStats>(keeper_dispatcher);
|
||||
factory.registerCommand(jemalloc_dump_stats);
|
||||
|
||||
FourLetterCommandPtr jemalloc_flush_profile = std::make_shared<JemallocFlushProfile>(keeper_dispatcher);
|
||||
factory.registerCommand(jemalloc_flush_profile);
|
||||
|
||||
FourLetterCommandPtr jemalloc_enable_profile = std::make_shared<JemallocEnableProfile>(keeper_dispatcher);
|
||||
factory.registerCommand(jemalloc_enable_profile);
|
||||
|
||||
FourLetterCommandPtr jemalloc_disable_profile = std::make_shared<JemallocDisableProfile>(keeper_dispatcher);
|
||||
factory.registerCommand(jemalloc_disable_profile);
|
||||
#endif
|
||||
|
||||
factory.initializeAllowList(keeper_dispatcher);
|
||||
factory.setInitialize(true);
|
||||
}
|
||||
@ -588,4 +607,37 @@ String YieldLeadershipCommand::run()
|
||||
return "Sent yield leadership request to leader.";
|
||||
}
|
||||
|
||||
#if USE_JEMALLOC
|
||||
|
||||
void printToString(void * output, const char * data)
|
||||
{
|
||||
std::string * output_data = reinterpret_cast<std::string *>(output);
|
||||
*output_data += std::string(data);
|
||||
}
|
||||
|
||||
String JemallocDumpStats::run()
|
||||
{
|
||||
std::string output;
|
||||
malloc_stats_print(printToString, &output, nullptr);
|
||||
return output;
|
||||
}
|
||||
|
||||
String JemallocFlushProfile::run()
|
||||
{
|
||||
return flushJemallocProfile("/tmp/jemalloc_keeper");
|
||||
}
|
||||
|
||||
String JemallocEnableProfile::run()
|
||||
{
|
||||
setJemallocProfileActive(true);
|
||||
return "ok";
|
||||
}
|
||||
|
||||
String JemallocDisableProfile::run()
|
||||
{
|
||||
setJemallocProfileActive(false);
|
||||
return "ok";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -428,4 +428,55 @@ struct YieldLeadershipCommand : public IFourLetterCommand
|
||||
~YieldLeadershipCommand() override = default;
|
||||
};
|
||||
|
||||
#if USE_JEMALLOC
|
||||
struct JemallocDumpStats : public IFourLetterCommand
|
||||
{
|
||||
explicit JemallocDumpStats(KeeperDispatcher & keeper_dispatcher_)
|
||||
: IFourLetterCommand(keeper_dispatcher_)
|
||||
{
|
||||
}
|
||||
|
||||
String name() override { return "jmst"; }
|
||||
String run() override;
|
||||
~JemallocDumpStats() override = default;
|
||||
|
||||
};
|
||||
|
||||
struct JemallocFlushProfile : public IFourLetterCommand
|
||||
{
|
||||
explicit JemallocFlushProfile(KeeperDispatcher & keeper_dispatcher_)
|
||||
: IFourLetterCommand(keeper_dispatcher_)
|
||||
{
|
||||
}
|
||||
|
||||
String name() override { return "jmfp"; }
|
||||
String run() override;
|
||||
~JemallocFlushProfile() override = default;
|
||||
};
|
||||
|
||||
struct JemallocEnableProfile : public IFourLetterCommand
|
||||
{
|
||||
explicit JemallocEnableProfile(KeeperDispatcher & keeper_dispatcher_)
|
||||
: IFourLetterCommand(keeper_dispatcher_)
|
||||
{
|
||||
}
|
||||
|
||||
String name() override { return "jmep"; }
|
||||
String run() override;
|
||||
~JemallocEnableProfile() override = default;
|
||||
};
|
||||
|
||||
struct JemallocDisableProfile : public IFourLetterCommand
|
||||
{
|
||||
explicit JemallocDisableProfile(KeeperDispatcher & keeper_dispatcher_)
|
||||
: IFourLetterCommand(keeper_dispatcher_)
|
||||
{
|
||||
}
|
||||
|
||||
String name() override { return "jmdp"; }
|
||||
String run() override;
|
||||
~JemallocDisableProfile() override = default;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -15,16 +15,10 @@
|
||||
#include <atomic>
|
||||
#include <future>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
#if USE_JEMALLOC
|
||||
# include <jemalloc/jemalloc.h>
|
||||
|
||||
#define STRINGIFY_HELPER(x) #x
|
||||
#define STRINGIFY(x) STRINGIFY_HELPER(x)
|
||||
|
||||
#include <Common/Jemalloc.h>
|
||||
#endif
|
||||
|
||||
namespace CurrentMetrics
|
||||
@ -33,12 +27,6 @@ namespace CurrentMetrics
|
||||
extern const Metric KeeperOutstandingRequets;
|
||||
}
|
||||
|
||||
namespace ProfileEvents
|
||||
{
|
||||
extern const Event MemoryAllocatorPurge;
|
||||
extern const Event MemoryAllocatorPurgeTimeMicroseconds;
|
||||
}
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace DB
|
||||
@ -986,11 +974,7 @@ Keeper4LWInfo KeeperDispatcher::getKeeper4LWInfo() const
|
||||
void KeeperDispatcher::cleanResources()
|
||||
{
|
||||
#if USE_JEMALLOC
|
||||
LOG_TRACE(&Poco::Logger::get("KeeperDispatcher"), "Purging unused memory");
|
||||
Stopwatch watch;
|
||||
mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".purge", nullptr, nullptr, nullptr, 0);
|
||||
ProfileEvents::increment(ProfileEvents::MemoryAllocatorPurge);
|
||||
ProfileEvents::increment(ProfileEvents::MemoryAllocatorPurgeTimeMicroseconds, watch.elapsedMicroseconds());
|
||||
purgeJemallocArenas();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,10 @@
|
||||
#include <IO/S3/Client.h>
|
||||
#endif
|
||||
|
||||
#if USE_JEMALLOC
|
||||
#include <Common/Jemalloc.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
namespace CurrentMetrics
|
||||
@ -98,7 +102,6 @@ namespace ErrorCodes
|
||||
extern const int SUPPORT_IS_DISABLED;
|
||||
}
|
||||
|
||||
|
||||
namespace ActionLocks
|
||||
{
|
||||
extern const StorageActionBlockType PartsMerge;
|
||||
@ -728,6 +731,33 @@ BlockIO InterpreterSystemQuery::execute()
|
||||
resetCoverage();
|
||||
break;
|
||||
}
|
||||
|
||||
#if USE_JEMALLOC
|
||||
case Type::JEMALLOC_PURGE:
|
||||
{
|
||||
getContext()->checkAccess(AccessType::SYSTEM_JEMALLOC);
|
||||
purgeJemallocArenas();
|
||||
break;
|
||||
}
|
||||
case Type::JEMALLOC_ENABLE_PROFILE:
|
||||
{
|
||||
getContext()->checkAccess(AccessType::SYSTEM_JEMALLOC);
|
||||
setJemallocProfileActive(true);
|
||||
break;
|
||||
}
|
||||
case Type::JEMALLOC_DISABLE_PROFILE:
|
||||
{
|
||||
getContext()->checkAccess(AccessType::SYSTEM_JEMALLOC);
|
||||
setJemallocProfileActive(false);
|
||||
break;
|
||||
}
|
||||
case Type::JEMALLOC_FLUSH_PROFILE:
|
||||
{
|
||||
getContext()->checkAccess(AccessType::SYSTEM_JEMALLOC);
|
||||
flushJemallocProfile("/tmp/jemalloc_clickhouse");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unknown type of SYSTEM query");
|
||||
}
|
||||
@ -1368,6 +1398,16 @@ AccessRightsElements InterpreterSystemQuery::getRequiredAccessForDDLOnCluster()
|
||||
required_access.emplace_back(AccessType::SYSTEM_LISTEN);
|
||||
break;
|
||||
}
|
||||
#if USE_JEMALLOC
|
||||
case Type::JEMALLOC_PURGE:
|
||||
case Type::JEMALLOC_ENABLE_PROFILE:
|
||||
case Type::JEMALLOC_DISABLE_PROFILE:
|
||||
case Type::JEMALLOC_FLUSH_PROFILE:
|
||||
{
|
||||
required_access.emplace_back(AccessType::SYSTEM_JEMALLOC);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case Type::STOP_THREAD_FUZZER:
|
||||
case Type::START_THREAD_FUZZER:
|
||||
case Type::ENABLE_FAILPOINT:
|
||||
|
@ -46,6 +46,12 @@ public:
|
||||
WAIT_LOADING_PARTS,
|
||||
DROP_REPLICA,
|
||||
DROP_DATABASE_REPLICA,
|
||||
#if USE_JEMALLOC
|
||||
JEMALLOC_PURGE,
|
||||
JEMALLOC_ENABLE_PROFILE,
|
||||
JEMALLOC_DISABLE_PROFILE,
|
||||
JEMALLOC_FLUSH_PROFILE,
|
||||
#endif
|
||||
SYNC_REPLICA,
|
||||
SYNC_DATABASE_REPLICA,
|
||||
SYNC_TRANSACTION_LOG,
|
||||
|
@ -150,6 +150,7 @@ SYSTEM THREAD FUZZER ['SYSTEM START THREAD FUZZER','SYSTEM STOP THREAD FUZZER','
|
||||
SYSTEM UNFREEZE ['SYSTEM UNFREEZE'] GLOBAL SYSTEM
|
||||
SYSTEM FAILPOINT ['SYSTEM ENABLE FAILPOINT','SYSTEM DISABLE FAILPOINT'] GLOBAL SYSTEM
|
||||
SYSTEM LISTEN ['SYSTEM START LISTEN','SYSTEM STOP LISTEN'] GLOBAL SYSTEM
|
||||
SYSTEM JEMALLOC ['SYSTEM JEMALLOC PURGE','SYSTEM JEMALLOC ENABLE PROFILE','SYSTEM JEMALLOC DISABLE PROFILE','SYSTEM JEMALLOC FLUSH PROFILE'] GLOBAL SYSTEM
|
||||
SYSTEM [] \N ALL
|
||||
dictGet ['dictHas','dictGetHierarchy','dictIsIn'] DICTIONARY ALL
|
||||
displaySecretsInShowAndSelect [] GLOBAL ALL
|
||||
|
Loading…
Reference in New Issue
Block a user