aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan <ilezhankin@yandex-team.ru>2024-11-28 00:11:13 +0300
committerGitHub <noreply@github.com>2024-11-28 00:11:13 +0300
commit4559701817441f8db881b59f4ad03fe4a31801d5 (patch)
treedf9441d3bf3912978f8e06c6772e70fac64b24b3
parente6457a7cafc1cf8b50efa2d1c8919dd6a99c4743 (diff)
downloadydb-4559701817441f8db881b59f4ad03fe4a31801d5.tar.gz
Print the heap stats when tcmalloc memory limit is hit (#11968)HEADmain
-rw-r--r--ydb/core/mon_alloc/tcmalloc.cpp101
-rw-r--r--ydb/core/mon_alloc/ya.make7
2 files changed, 97 insertions, 11 deletions
diff --git a/ydb/core/mon_alloc/tcmalloc.cpp b/ydb/core/mon_alloc/tcmalloc.cpp
index d16f58d735..db1796336b 100644
--- a/ydb/core/mon_alloc/tcmalloc.cpp
+++ b/ydb/core/mon_alloc/tcmalloc.cpp
@@ -3,19 +3,19 @@
#include <contrib/libs/tcmalloc/tcmalloc/malloc_extension.h>
#include <ydb/library/actors/prof/tag.h>
-#include <library/cpp/cache/cache.h>
+#include <ydb/core/mon/mon.h>
+#include <library/cpp/cache/cache.h>
#if defined(USE_DWARF_BACKTRACE)
# include <library/cpp/dwarf_backtrace/backtrace.h>
#endif
-
#include <library/cpp/html/pcdata/pcdata.h>
#include <library/cpp/monlib/service/pages/templates.h>
-#include <ydb/core/mon/mon.h>
-
#include <util/stream/format.h>
+#include <thread>
+
using namespace NActors;
namespace NKikimr {
@@ -478,6 +478,91 @@ public:
};
+void HandleTcMallocSoftLimit();
+
+class TTcMallocLimitHandler : public TSingletonTraits<TTcMallocLimitHandler> {
+public:
+ Y_DECLARE_SINGLETON_FRIEND();
+
+ ~TTcMallocLimitHandler() {
+ if (Thread_.joinable()) {
+ {
+ std::unique_lock<std::mutex> lock(Mutex_);
+ JustQuit_ = true;
+ }
+ Fire();
+ Thread_.join();
+ }
+ }
+
+ void SetOutputStream(IOutputStream& out) {
+ Out_ = &out;
+ }
+
+ void Fire() {
+ std::unique_lock<std::mutex> lock(Mutex_);
+ Fired_ = true;
+ CV_.notify_all();
+ }
+
+private:
+ TTcMallocLimitHandler() {
+ tcmalloc::MallocExtension::EnableForkSupport();
+ tcmalloc::MallocExtension::SetSoftMemoryLimitHandler(&HandleTcMallocSoftLimit);
+ Thread_ = std::thread(&TTcMallocLimitHandler::Handle, this);
+ }
+
+private:
+ std::mutex Mutex_;
+ bool Fired_ = false; // protected by Mutex_
+ bool JustQuit_ = false; // protected by Mutex_
+ std::condition_variable CV_; // protected by Mutex_
+
+ IOutputStream* Out_ = &Cerr;
+ std::thread Thread_;
+
+ void Handle() {
+ std::unique_lock<std::mutex> lock(Mutex_);
+ CV_.wait(lock, [&] {
+ return Fired_;
+ });
+
+ if (JustQuit_) {
+ return;
+ }
+
+ *Out_ << tcmalloc::MallocExtension::GetStats() << Endl;
+
+ if (auto childPid = fork(); childPid == 0) {
+ kill(getppid(), SIGSTOP);
+
+ *Out_ << "Child: " << getpid() << ", parent process stopped: " << getppid() << Endl;
+
+ try {
+ auto profile = tcmalloc::MallocExtension::SnapshotCurrent(tcmalloc::ProfileType::kHeap);
+ TAllocationAnalyzer analyzer(std::move(profile));
+ TAllocationStats allocationStats;
+ analyzer.Prepare(&allocationStats);
+ analyzer.Dump(*Out_, 256, 1024, true, true);
+ } catch (...) {
+ kill(getppid(), SIGCONT);
+ throw;
+ }
+
+ kill(getppid(), SIGCONT);
+ } else if (childPid < 0) {
+ *Out_ << "Failed to dump current heap: fork failed" << Endl;
+ }
+
+ // TODO: probably should wait for child, but we're going to OOM anyway.
+ }
+};
+
+void HandleTcMallocSoftLimit() {
+ Singleton<TTcMallocLimitHandler>()->Fire();
+}
+
+
class TTcMallocMonitor : public IAllocMonitor {
TDynamicCountersPtr CounterGroup;
@@ -694,6 +779,11 @@ public:
CountHistogram = CounterGroup->GetHistogram("tcmalloc.sampled_count",
NMonitoring::ExponentialHistogram(TAllocationStats::MaxSizeIndex, 2, 1), false);
+
+#ifdef PROFILE_MEMORY_ALLOCATIONS
+ // Setup tcmalloc soft limit handling
+ Singleton<TTcMallocLimitHandler>();
+#endif
}
void RegisterPages(TMon* mon, TActorSystem* actorSystem, TActorId actorId) override {
@@ -807,6 +897,7 @@ public:
}
};
+// Public functions
std::unique_ptr<IAllocStats> CreateTcMallocStats(TDynamicCountersPtr group) {
return std::make_unique<TTcMallocStats>(std::move(group));
@@ -824,4 +915,4 @@ std::unique_ptr<IProfilerLogic> CreateTcMallocProfiler() {
return std::make_unique<TTcMallocProfiler>();
}
-}
+} // namespace NKikimr
diff --git a/ydb/core/mon_alloc/ya.make b/ydb/core/mon_alloc/ya.make
index 6591349bf2..9210af29de 100644
--- a/ydb/core/mon_alloc/ya.make
+++ b/ydb/core/mon_alloc/ya.make
@@ -1,11 +1,5 @@
LIBRARY()
-IF (PROFILE_MEMORY_ALLOCATIONS)
- CFLAGS(
- -DPROFILE_MEMORY_ALLOCATIONS
- )
-ENDIF()
-
SRCS(
memory_info.cpp
monitor.cpp
@@ -35,6 +29,7 @@ PEERDIR(
ydb/library/actors/core
ydb/library/actors/prof
ydb/library/services
+ yql/essentials/utils/memory_profiling
)
END()