aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbabenko <babenko@yandex-team.com>2024-09-09 18:48:41 +0300
committerbabenko <babenko@yandex-team.com>2024-09-09 19:02:18 +0300
commitd3e48fe4feee0750b9edd6b987e4637d4f678f29 (patch)
tree59e6c11bf3828c3683d65a4dcface6fbae8ced9c
parentab9b1efed10713e3420ece39a521ec5273efd375 (diff)
downloadydb-d3e48fe4feee0750b9edd6b987e4637d4f678f29.tar.gz
YT-22593: Switch (some) trace context tags to std::string and refactor code around [TRIVIAL]
643d86a500b7db9df11009f54364b468b29a409a
-rw-r--r--library/cpp/yt/memory/allocation_tags.h16
-rw-r--r--library/cpp/yt/memory/allocation_tags_hooks.cpp27
-rw-r--r--library/cpp/yt/memory/allocation_tags_hooks.h23
-rw-r--r--library/cpp/yt/memory/ya.make1
-rw-r--r--yt/yt/core/rpc/helpers.cpp5
-rw-r--r--yt/yt/core/rpc/unittests/rpc_allocation_tags_ut.cpp1
-rw-r--r--yt/yt/core/tracing/allocation_hooks.cpp75
-rw-r--r--yt/yt/core/tracing/allocation_tags.cpp61
-rw-r--r--yt/yt/core/tracing/allocation_tags.h51
-rw-r--r--yt/yt/core/tracing/allocation_tags_hooks.cpp116
-rw-r--r--yt/yt/core/tracing/public.h11
-rw-r--r--yt/yt/core/tracing/trace_context-inl.h105
-rw-r--r--yt/yt/core/tracing/trace_context.cpp115
-rw-r--r--yt/yt/core/tracing/trace_context.h73
-rw-r--r--yt/yt/core/tracing/unittests/allocation_tags_ut.cpp24
-rw-r--r--yt/yt/core/ya.make7
-rw-r--r--yt/yt/library/tracing/jaeger/tracer.cpp6
-rw-r--r--yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.cpp40
-rw-r--r--yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.h2
-rw-r--r--yt/yt/library/ytprof/api/api.h2
-rw-r--r--yt/yt/library/ytprof/cpu_profiler.cpp6
-rw-r--r--yt/yt/library/ytprof/cpu_profiler.h2
-rw-r--r--yt/yt/library/ytprof/heap_profiler.cpp251
-rw-r--r--yt/yt/library/ytprof/heap_profiler.h41
-rw-r--r--yt/yt/library/ytprof/signal_safe_profiler.cpp38
-rw-r--r--yt/yt/library/ytprof/signal_safe_profiler.h5
-rw-r--r--yt/yt/library/ytprof/spinlock_profiler.cpp5
-rw-r--r--yt/yt/library/ytprof/spinlock_profiler.h4
-rw-r--r--yt/yt/library/ytprof/unittests/heap_profiler_ut.cpp111
29 files changed, 580 insertions, 644 deletions
diff --git a/library/cpp/yt/memory/allocation_tags.h b/library/cpp/yt/memory/allocation_tags.h
new file mode 100644
index 0000000000..5bd0f415c6
--- /dev/null
+++ b/library/cpp/yt/memory/allocation_tags.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include <string>
+#include <utility>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+using TAllocationTagKey = std::string;
+using TAllocationTagValue = std::string;
+using TAllocationTag = std::pair<TAllocationTagKey, TAllocationTagValue>;
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
diff --git a/library/cpp/yt/memory/allocation_tags_hooks.cpp b/library/cpp/yt/memory/allocation_tags_hooks.cpp
new file mode 100644
index 0000000000..dc6d531f3e
--- /dev/null
+++ b/library/cpp/yt/memory/allocation_tags_hooks.cpp
@@ -0,0 +1,27 @@
+#include "allocation_tags_hooks.h"
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+Y_WEAK const TAllocationTagsHooks& GetAllocationTagsHooks()
+{
+ static const TAllocationTagsHooks hooks{
+ .CreateAllocationTags = [] () -> void* {
+ return nullptr;
+ },
+ .CopyAllocationTags = [] (void* /*opaque*/) -> void* {
+ return nullptr;
+ },
+ .DestroyAllocationTags = [] (void* /*opaque*/) {
+ },
+ .ReadAllocationTags = [] (void* /*opaque*/) -> TRange<TAllocationTag> {
+ return {};
+ },
+ };
+ return hooks;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
diff --git a/library/cpp/yt/memory/allocation_tags_hooks.h b/library/cpp/yt/memory/allocation_tags_hooks.h
new file mode 100644
index 0000000000..57673f68b0
--- /dev/null
+++ b/library/cpp/yt/memory/allocation_tags_hooks.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "allocation_tags.h"
+
+#include <library/cpp/yt/memory/range.h>
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct TAllocationTagsHooks
+{
+ void* (*CreateAllocationTags)();
+ void* (*CopyAllocationTags)(void* opaque);
+ void (*DestroyAllocationTags)(void* opaque);
+ TRange<TAllocationTag> (*ReadAllocationTags)(void* opaque);
+};
+
+const TAllocationTagsHooks& GetAllocationTagsHooks();
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
diff --git a/library/cpp/yt/memory/ya.make b/library/cpp/yt/memory/ya.make
index 9dc4372729..c2d78b0d07 100644
--- a/library/cpp/yt/memory/ya.make
+++ b/library/cpp/yt/memory/ya.make
@@ -3,6 +3,7 @@ LIBRARY()
INCLUDE(${ARCADIA_ROOT}/library/cpp/yt/ya_cpp.make.inc)
SRCS(
+ allocation_tags_hooks.cpp
blob.cpp
chunked_input_stream.cpp
chunked_memory_allocator.cpp
diff --git a/yt/yt/core/rpc/helpers.cpp b/yt/yt/core/rpc/helpers.cpp
index c6fbdaa099..9341cbc51b 100644
--- a/yt/yt/core/rpc/helpers.cpp
+++ b/yt/yt/core/rpc/helpers.cpp
@@ -446,10 +446,7 @@ TTraceContextPtr CreateCallTraceContext(std::string service, std::string method)
return oldTraceContext;
}
- auto traceContext = oldTraceContext->CreateChild(Format("RpcClient:%v.%v", service, method));
- traceContext->SetAllocationTagsPtr(oldTraceContext->GetAllocationTagsPtr());
-
- return traceContext;
+ return oldTraceContext->CreateChild(Format("RpcClient:%v.%v", service, method));
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/core/rpc/unittests/rpc_allocation_tags_ut.cpp b/yt/yt/core/rpc/unittests/rpc_allocation_tags_ut.cpp
index b2ad0c5ddf..919981feb0 100644
--- a/yt/yt/core/rpc/unittests/rpc_allocation_tags_ut.cpp
+++ b/yt/yt/core/rpc/unittests/rpc_allocation_tags_ut.cpp
@@ -32,6 +32,7 @@ TYPED_TEST(TRpcTest, ResponseWithAllocationTags)
auto memoryUsageTracker = this->GetMemoryUsageTracker();
auto previousLimit = memoryUsageTracker->GetLimit();
memoryUsageTracker->SetLimit(2_GB);
+
static TMemoryTag testMemoryTag = 1 << 20;
testMemoryTag++;
diff --git a/yt/yt/core/tracing/allocation_hooks.cpp b/yt/yt/core/tracing/allocation_hooks.cpp
deleted file mode 100644
index 36be840cfa..0000000000
--- a/yt/yt/core/tracing/allocation_hooks.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "allocation_tags.h"
-#include "trace_context.h"
-
-#include <library/cpp/yt/memory/leaky_singleton.h>
-
-#include <thread>
-
-namespace NYT {
-
-////////////////////////////////////////////////////////////////////////////////
-
-using namespace NTracing;
-
-static auto* FreeList = LeakySingleton<TAllocationTagsFreeList>();
-
-void* CreateAllocationTagsData()
-{
- auto* traceContext = TryGetCurrentTraceContext();
- if (!traceContext) {
- return nullptr;
- }
-
- // Need to avoid deadlock from TTraceContext->SetAllocationTags due another allocation.
- auto allocationTags = traceContext->GetAllocationTagsPtr();
-
- return static_cast<void*>(allocationTags.Release());
-}
-
-void* CopyAllocationTagsData(void* userData)
-{
- if (userData) {
- auto* allocationTagsPtr = static_cast<TAllocationTags*>(userData);
- allocationTagsPtr->Ref();
- }
- return userData;
-}
-
-void DestroyAllocationTagsData(void* userData)
-{
- auto* allocationTagsPtr = static_cast<TAllocationTags*>(userData);
- // NB. No need to check for nullptr here, because ScheduleFree already does that.
- FreeList->ScheduleFree(allocationTagsPtr);
-}
-
-const TAllocationTags::TTags* ReadAllocationTagsData(void* userData)
-{
- if (!userData) {
- return nullptr;
- }
-
- const auto* allocationTagsPtr = static_cast<TAllocationTags*>(userData);
- return allocationTagsPtr->GetTagsPtr();
-}
-
-std::optional<TString> FindTagValue(
- const TAllocationTags::TTags& tags,
- const TString& key)
-{
- return TAllocationTags::FindTagValue(tags, key);
-}
-
-void StartAllocationTagsCleanupThread(TDuration cleanupInterval)
-{
- std::thread backgroundThread([cleanupInterval] {
- for (;;) {
- FreeList->Cleanup();
- Sleep(cleanupInterval);
- }
- });
- backgroundThread.detach();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-} // namespace NYT
diff --git a/yt/yt/core/tracing/allocation_tags.cpp b/yt/yt/core/tracing/allocation_tags.cpp
index e38154db17..7bd7d043a8 100644
--- a/yt/yt/core/tracing/allocation_tags.cpp
+++ b/yt/yt/core/tracing/allocation_tags.cpp
@@ -4,70 +4,23 @@ namespace NYT::NTracing {
////////////////////////////////////////////////////////////////////////////////
-TAllocationTags::TAllocationTags(std::vector<std::pair<TString, TString>> tags)
+TAllocationTagList::TAllocationTagList(TAllocationTags tags)
: Tags_(std::move(tags))
{ }
-const TAllocationTags::TTags& TAllocationTags::GetTags() const noexcept
+const TAllocationTags& TAllocationTagList::GetTags() const noexcept
{
return Tags_;
}
-const TAllocationTags::TTags* TAllocationTags::GetTagsPtr() const noexcept
+std::optional<TAllocationTagValue> TAllocationTagList::FindTagValue(const TAllocationTagKey& key) const
{
- return &Tags_;
-}
-
-std::optional<TAllocationTags::TValue> TAllocationTags::FindTagValue(const TKey& key) const
-{
- return FindTagValue(Tags_, key);
-}
-
-std::optional<TAllocationTags::TValue> TAllocationTags::FindTagValue(
- const TTags& tags,
- const TKey& key)
-{
- std::optional<TAllocationTags::TValue> value;
-
- for (const auto& [key_, value_] : tags) {
- if (key_ == key) {
- value = value_;
- break;
+ for (const auto& [someKey, someValue] : Tags_) {
+ if (someKey == key) {
+ return someValue;
}
}
-
- return value;
-}
-
-TAllocationTagsFreeList::~TAllocationTagsFreeList()
-{
- Cleanup();
-}
-
-void TAllocationTagsFreeList::ScheduleFree(TAllocationTags* tagsRawPtr)
-{
- if (tagsRawPtr == nullptr) {
- return;
- }
- if (!GetRefCounter(tagsRawPtr)->Unref()) {
- return;
- }
- YT_VERIFY(tagsRawPtr->Next_ == nullptr);
- auto guard = Guard(Spinlock_);
- tagsRawPtr->Next_ = Head_;
- Head_ = tagsRawPtr;
-}
-
-void TAllocationTagsFreeList::Cleanup()
-{
- auto guard = Guard(Spinlock_);
- auto head = std::exchange(Head_, nullptr);
- guard.Release();
- while (head != nullptr) {
- auto oldHead = head;
- head = head->Next_;
- DestroyRefCounted(oldHead);
- }
+ return std::nullopt;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/core/tracing/allocation_tags.h b/yt/yt/core/tracing/allocation_tags.h
index ea7b5a6447..69960431ce 100644
--- a/yt/yt/core/tracing/allocation_tags.h
+++ b/yt/yt/core/tracing/allocation_tags.h
@@ -2,59 +2,28 @@
#include "public.h"
-#include <library/cpp/yt/threading/spin_lock.h>
+#include <yt/yt/core/misc/intrusive_mpsc_stack.h>
namespace NYT::NTracing {
////////////////////////////////////////////////////////////////////////////////
-class TAllocationTags : public TRefCounted
+//! An immutable ref-counted list of allocation tags.
+class TAllocationTagList
+ : public TRefCounted
+ , public TIntrusiveListItem<TAllocationTagList>
{
public:
- using TKey = TString;
- using TValue = TString;
- using TTags = std::vector<std::pair<TKey, TValue>>;
+ explicit TAllocationTagList(TAllocationTags tags);
- explicit TAllocationTags(TTags tags);
-
- const TTags& GetTags() const noexcept;
-
- const TTags* GetTagsPtr() const noexcept;
-
- std::optional<TValue> FindTagValue(const TKey& key) const;
-
- static std::optional<TValue> FindTagValue(
- const TTags& tags,
- const TKey& key);
+ const TAllocationTags& GetTags() const noexcept;
+ std::optional<TAllocationTagValue> FindTagValue(const TAllocationTagKey& key) const;
private:
- friend class TAllocationTagsFreeList;
-
- const TTags Tags_;
- TAllocationTags* Next_ = nullptr;
+ const TAllocationTags Tags_;
};
-DEFINE_REFCOUNTED_TYPE(TAllocationTags)
-
-class TAllocationTagsFreeList
-{
-public:
- //! Decreases refcount of tagsRawPtr. If refcount becomes zero, puts the pointer into queue.
- //!
- //! The intended usage is
- //! list->ScheduleFree(tags.Release());
- //! where tags is TAllocationTagsPtr.
- void ScheduleFree(TAllocationTags* tagsRawPtr);
-
- //! Free all the pointers in the queue.
- void Cleanup();
-
- ~TAllocationTagsFreeList();
-
-private:
- YT_DECLARE_SPIN_LOCK(NThreading::TSpinLock, Spinlock_);
- TAllocationTags* Head_ = nullptr;
-};
+DEFINE_REFCOUNTED_TYPE(TAllocationTagList)
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/core/tracing/allocation_tags_hooks.cpp b/yt/yt/core/tracing/allocation_tags_hooks.cpp
new file mode 100644
index 0000000000..1ded85fdc8
--- /dev/null
+++ b/yt/yt/core/tracing/allocation_tags_hooks.cpp
@@ -0,0 +1,116 @@
+#include "trace_context.h"
+
+#include <library/cpp/yt/memory/allocation_tags_hooks.h>
+#include <library/cpp/yt/memory/leaky_singleton.h>
+
+#include <util/system/thread.h>
+
+#include <thread>
+
+namespace NYT::NTracing {
+
+////////////////////////////////////////////////////////////////////////////////
+
+class TAllocationTagsReclaimer
+{
+public:
+ TAllocationTagsReclaimer()
+ {
+ std::thread thread([this] {
+ TThread::SetCurrentThreadName("AllocTagsReclaim");
+ while (true) {
+ DoReclaim();
+ Sleep(ReclaimPeriod);
+ }
+ });
+ thread.detach();
+ }
+
+ void ScheduleReclaim(TAllocationTagList* list)
+ {
+ if (GetRefCounter(list)->Unref()) {
+ ListsToReclaim_.Push(list);
+ }
+ }
+
+ static TAllocationTagsReclaimer* Get()
+ {
+ return LeakySingleton<TAllocationTagsReclaimer>();
+ }
+
+private:
+ TIntrusiveMpscStack<TAllocationTagList> ListsToReclaim_;
+
+ static constexpr TDuration ReclaimPeriod = TDuration::Seconds(5);
+
+ void DoReclaim()
+ {
+ auto items = ListsToReclaim_.PopAll();
+ while (!items.Empty()) {
+ DestroyRefCounted(items.PopFront()->Node());
+ }
+ }
+};
+
+void* CreateAllocationTags()
+{
+ const auto* traceContext = TryGetCurrentTraceContext();
+ if (!traceContext) {
+ return nullptr;
+ }
+
+ return traceContext->GetAllocationTagList().Release();
+}
+
+void* CopyAllocationTags(void* opaque)
+{
+ if (opaque) {
+ static_cast<TAllocationTagList*>(opaque)->Ref();
+ }
+
+ return opaque;
+}
+
+void DestroyAllocationTags(void* opaque)
+{
+ if (auto* list = static_cast<TAllocationTagList*>(opaque)) {
+ TAllocationTagsReclaimer::Get()->ScheduleReclaim(list);
+ }
+}
+
+TRange<TAllocationTag> ReadAllocationTags(void* opaque)
+{
+ if (!opaque) {
+ return {};
+ }
+
+ const auto* list = static_cast<TAllocationTagList*>(opaque);
+ return list->GetTags();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT::NTracing
+
+namespace NYT {
+
+using namespace NTracing;
+
+////////////////////////////////////////////////////////////////////////////////
+
+const TAllocationTagsHooks& GetAllocationTagsHooks()
+{
+ // Boot the reclaimer up here, in a seemingly safe context.
+ TAllocationTagsReclaimer::Get();
+ static const TAllocationTagsHooks hooks{
+ .CreateAllocationTags = CreateAllocationTags,
+ .CopyAllocationTags = CopyAllocationTags,
+ .DestroyAllocationTags = DestroyAllocationTags,
+ .ReadAllocationTags = ReadAllocationTags,
+ };
+ return hooks;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
diff --git a/yt/yt/core/tracing/public.h b/yt/yt/core/tracing/public.h
index 9d864133aa..1afb4c6009 100644
--- a/yt/yt/core/tracing/public.h
+++ b/yt/yt/core/tracing/public.h
@@ -4,6 +4,10 @@
#include <library/cpp/yt/misc/guid.h>
+#include <library/cpp/yt/small_containers/compact_vector.h>
+
+#include <library/cpp/yt/memory/allocation_tags.h>
+
namespace NYT::NTracing {
////////////////////////////////////////////////////////////////////////////////
@@ -14,11 +18,16 @@ class TTracingExt;
} // namespace NProto
+////////////////////////////////////////////////////////////////////////////////
+
DECLARE_REFCOUNTED_CLASS(TTraceContext)
DECLARE_REFCOUNTED_CLASS(TTracingTransportConfig)
-DECLARE_REFCOUNTED_CLASS(TAllocationTags)
+constexpr int TypicalAllocationTagCount = 8;
+using TAllocationTags = TCompactVector<TAllocationTag, TypicalAllocationTagCount>;
+
+DECLARE_REFCOUNTED_CLASS(TAllocationTagList)
using TTraceId = TGuid;
constexpr TTraceId InvalidTraceId = {};
diff --git a/yt/yt/core/tracing/trace_context-inl.h b/yt/yt/core/tracing/trace_context-inl.h
index 640fcaa2a6..a856735430 100644
--- a/yt/yt/core/tracing/trace_context-inl.h
+++ b/yt/yt/core/tracing/trace_context-inl.h
@@ -75,105 +75,60 @@ Y_FORCE_INLINE NProfiling::TCpuDuration TTraceContext::GetElapsedCpuTime() const
}
template <class T>
-void TTraceContext::AddTag(const TString& tagName, const T& tagValue)
+void TTraceContext::AddTag(const std::string& tagName, const T& tagValue)
{
if (!IsRecorded()) {
return;
}
using ::ToString;
- AddTag(tagName, ToString(tagValue));
+ // TODO(babenko): migrate to std::string
+ AddTag(tagName, std::string(ToString(tagValue)));
}
-template <typename TTag>
-std::optional<TTag> TTraceContext::DoFindAllocationTag(const TString& key) const
+template <typename T>
+std::optional<T> TTraceContext::FindAllocationTag(const TAllocationTagKey& key) const
{
- VERIFY_SPINLOCK_AFFINITY(AllocationTagsLock_);
-
- TAllocationTagsPtr tags;
-
- {
- // Local guard for copy RefCounted AllocationTags_.
- auto guard = Guard(AllocationTagsAsRefCountedLock_);
- tags = AllocationTags_;
- }
-
- if (tags) {
- auto valueOpt = tags->FindTagValue(key);
-
- if (valueOpt.has_value()) {
- return FromString<TTag>(valueOpt.value());
+ // NB: No lock is needed.
+ if (auto list = AllocationTagList_.Acquire()) {
+ if (auto optionalValue = list->FindTagValue(key)) {
+ return FromString<T>(*optionalValue);
}
}
-
return std::nullopt;
}
-template <typename TTag>
-std::optional<TTag> TTraceContext::FindAllocationTag(const TString& key) const
-{
- auto readerGuard = ReaderGuard(AllocationTagsLock_);
- return DoFindAllocationTag<TTag>(key);
-}
-
-template <typename TTag>
-std::optional<TTag> TTraceContext::RemoveAllocationTag(const TString& key)
-{
- auto writerGuard = NThreading::WriterGuard(AllocationTagsLock_);
- auto newTags = DoGetAllocationTags();
-
- auto foundTagIt = std::remove_if(
- newTags.begin(),
- newTags.end(),
- [&key] (const auto& pair) {
- return pair.first == key;
- });
-
- std::optional<TTag> oldTag;
-
- if (foundTagIt != newTags.end()) {
- oldTag = FromString<TTag>(foundTagIt->second);
- }
-
- newTags.erase(foundTagIt, newTags.end());
-
- DoSetAllocationTags(std::move(newTags));
-
- return oldTag;
-}
-
-template <typename TTag>
-std::optional<TTag> TTraceContext::SetAllocationTag(const TString& key, TTag newTag)
+template <typename T>
+std::optional<T> TTraceContext::SetAllocationTag(const TAllocationTagKey& key, const T& value)
{
- auto newTagString = ToString(newTag);
+ auto newTagValue = ToString(value);
- auto writerGuard = NThreading::WriterGuard(AllocationTagsLock_);
- auto newTags = DoGetAllocationTags();
+ auto guard = Guard(AllocationTagsLock_);
+ auto newTags = GetAllocationTags();
if (!newTags.empty()) {
- std::optional<TString> oldTag;
-
- auto tagIt = std::find_if(
+ auto it = std::find_if(
newTags.begin(),
newTags.end(),
- [&key] (const auto& pair) {
+ [&] (const auto& pair) {
return pair.first == key;
});
- if (tagIt != newTags.end()) {
- oldTag = std::move(tagIt->second);
- tagIt->second = std::move(newTagString);
+ std::optional<TAllocationTagValue> oldTagValue;
+ if (it != newTags.end()) {
+ oldTagValue = std::move(it->second);
+ it->second = std::move(newTagValue);
} else {
- newTags.emplace_back(key, std::move(newTagString));
+ newTags.emplace_back(key, std::move(newTagValue));
}
DoSetAllocationTags(std::move(newTags));
- if (oldTag.has_value()) {
- return FromString<TTag>(oldTag.value());
+ if (oldTagValue) {
+ return FromString<T>(*oldTagValue);
}
} else {
- DoSetAllocationTags({{key, std::move(newTagString)}});
+ DoSetAllocationTags({{key, std::move(newTagValue)}});
}
return std::nullopt;
@@ -286,18 +241,18 @@ inline bool TChildTraceContextGuard::IsRecorded(const TTraceContextPtr& traceCon
inline TChildTraceContextGuard::TChildTraceContextGuard(
const TTraceContextPtr& traceContext,
- TString spanName,
+ const std::string& spanName,
std::optional<NProfiling::TCpuInstant> startTime)
: TraceContextGuard_(IsRecorded(traceContext) ? traceContext->CreateChild(spanName, startTime) : nullptr)
, FinishGuard_(IsRecorded(traceContext) ? TryGetCurrentTraceContext() : nullptr)
{ }
inline TChildTraceContextGuard::TChildTraceContextGuard(
- TString spanName,
+ const std::string& spanName,
std::optional<NProfiling::TCpuInstant> startTime)
: TChildTraceContextGuard(
TryGetCurrentTraceContext(),
- std::move(spanName),
+ spanName,
startTime)
{ }
@@ -349,13 +304,13 @@ Y_FORCE_INLINE TTraceContext* GetCurrentTraceContext()
return NDetail::CurrentTraceContext();
}
-Y_FORCE_INLINE TTraceContextPtr CreateTraceContextFromCurrent(TString spanName)
+Y_FORCE_INLINE TTraceContextPtr CreateTraceContextFromCurrent(const std::string& spanName)
{
auto* context = TryGetCurrentTraceContext();
- return context ? context->CreateChild(std::move(spanName)) : TTraceContext::NewRoot(std::move(spanName));
+ return context ? context->CreateChild(spanName) : TTraceContext::NewRoot(spanName);
}
-Y_FORCE_INLINE TTraceContextPtr GetOrCreateTraceContext(TString spanNameIfCreate)
+Y_FORCE_INLINE TTraceContextPtr GetOrCreateTraceContext(const std::string& spanNameIfCreate)
{
auto* context = TryGetCurrentTraceContext();
return context ? context : TTraceContext::NewRoot(std::move(spanNameIfCreate));
diff --git a/yt/yt/core/tracing/trace_context.cpp b/yt/yt/core/tracing/trace_context.cpp
index 5be2f295db..1e3006b60b 100644
--- a/yt/yt/core/tracing/trace_context.cpp
+++ b/yt/yt/core/tracing/trace_context.cpp
@@ -255,7 +255,7 @@ void FormatValue(TStringBuilderBase* builder, const TSpanContext& context, TStri
TTraceContext::TTraceContext(
TSpanContext parentSpanContext,
- TString spanName,
+ const std::string& spanName,
TTraceContextPtr parentTraceContext,
std::optional<NProfiling::TCpuInstant> startTime)
: TraceId_(parentSpanContext.TraceId)
@@ -266,7 +266,7 @@ TTraceContext::TTraceContext(
? parentTraceContext->State_.load()
: (parentSpanContext.Sampled ? ETraceContextState::Sampled : ETraceContextState::Disabled))
, ParentContext_(std::move(parentTraceContext))
- , SpanName_(std::move(spanName))
+ , SpanName_(spanName)
, RequestId_(ParentContext_ ? ParentContext_->GetRequestId() : TRequestId{})
, TargetEndpoint_(ParentContext_ ? ParentContext_->GetTargetEndpoint() : std::nullopt)
, LoggingTag_(ParentContext_ ? ParentContext_->GetLoggingTag() : TString{})
@@ -291,75 +291,56 @@ void TTraceContext::SetLoggingTag(const TString& loggingTag)
LoggingTag_ = loggingTag;
}
-void TTraceContext::ClearAllocationTagsPtr() noexcept
+TAllocationTags TTraceContext::GetAllocationTags() const
{
- auto writerGuard = WriterGuard(AllocationTagsLock_);
- auto guard = Guard(AllocationTagsAsRefCountedLock_);
- AllocationTags_ = nullptr;
+ // NB: No lock is needed.
+ auto list = AllocationTagList_.Acquire();
+ return list ? list->GetTags() : TAllocationTags();
}
-TAllocationTags::TTags TTraceContext::DoGetAllocationTags() const
+void TTraceContext::SetAllocationTags(TAllocationTags&& tags)
{
- VERIFY_SPINLOCK_AFFINITY(AllocationTagsLock_);
+ auto guard = Guard(AllocationTagsLock_);
+ return DoSetAllocationTags(std::move(tags));
+}
- TAllocationTagsPtr tags;
+void TTraceContext::RemoveAllocationTag(const TAllocationTagKey& key)
+{
+ auto guard = Guard(AllocationTagsLock_);
- {
- // Local guard for copy RefCounted AllocationTags_.
- auto guard = Guard(AllocationTagsAsRefCountedLock_);
- tags = AllocationTags_;
- }
+ auto newTags = GetAllocationTags();
+ auto it = std::remove_if(
+ newTags.begin(),
+ newTags.end(),
+ [&] (const auto& pair) {
+ return pair.first == key;
+ });
- if (!tags) {
- return {};
+ if (it == newTags.end()) {
+ return;
}
- return tags->GetTags();
+ std::swap(newTags.back(), *it);
+ newTags.pop_back();
+ DoSetAllocationTags(std::move(newTags));
}
-TAllocationTags::TTags TTraceContext::GetAllocationTags() const
+TAllocationTagListPtr TTraceContext::GetAllocationTagList() const noexcept
{
- auto readerGuard = ReaderGuard(AllocationTagsLock_);
- return DoGetAllocationTags();
+ return AllocationTagList_.Acquire();
}
-TAllocationTagsPtr TTraceContext::GetAllocationTagsPtr() const noexcept
+void TTraceContext::SetAllocationTagList(TAllocationTagListPtr list) noexcept
{
- // Local guard for copy RefCounted AllocationTags_ for allocator callback CreateAllocationTagsData().
- auto guard = Guard(AllocationTagsAsRefCountedLock_);
-
- return AllocationTags_;
+ auto guard = Guard(AllocationTagsLock_);
+ AllocationTagList_.Store(std::move(list));
}
-void TTraceContext::SetAllocationTagsPtr(TAllocationTagsPtr allocationTags) noexcept
-{
- auto writerGuard = WriterGuard(AllocationTagsLock_);
-
- // Local guard for setting RefCounted AllocationTags_.
- auto guard = Guard(AllocationTagsAsRefCountedLock_);
-
- AllocationTags_ = std::move(allocationTags);
-}
-
-void TTraceContext::DoSetAllocationTags(TAllocationTags::TTags&& tags)
+void TTraceContext::DoSetAllocationTags(TAllocationTags&& tags)
{
VERIFY_SPINLOCK_AFFINITY(AllocationTagsLock_);
-
- TAllocationTagsPtr allocationTagsPtr;
- if (!tags.empty()) {
- // Allocation MUST be done BEFORE Guard(AllocationTagsAsRefCountedSpinlock_) to avoid deadlock with CreateAllocationTagsData().
- allocationTagsPtr = New<TAllocationTags>(std::move(tags));
- }
-
- auto guard = Guard(AllocationTagsAsRefCountedLock_);
- AllocationTags_ = std::move(allocationTagsPtr);
-}
-
-void TTraceContext::SetAllocationTags(TAllocationTags::TTags&& tags)
-{
- auto writerGuard = WriterGuard(AllocationTagsLock_);
-
- return DoSetAllocationTags(std::move(tags));
+ auto holder = tags.empty() ? nullptr : New<TAllocationTagList>(std::move(tags));
+ AllocationTagList_.Store(std::move(holder));
}
void TTraceContext::SetRecorded()
@@ -374,19 +355,19 @@ void TTraceContext::SetPropagated(bool value)
}
TTraceContextPtr TTraceContext::CreateChild(
- TString spanName,
+ const std::string& spanName,
std::optional<NProfiling::TCpuInstant> startTime)
{
auto child = New<TTraceContext>(
GetSpanContext(),
- std::move(spanName),
+ spanName,
/*parentTraceContext*/ this,
startTime);
auto guard = Guard(Lock_);
child->ProfilingTags_ = ProfilingTags_;
child->TargetEndpoint_ = TargetEndpoint_;
- child->AllocationTags_ = AllocationTags_;
+ child->AllocationTagList_.Store(AllocationTagList_.Acquire());
return child;
}
@@ -469,7 +450,7 @@ void TTraceContext::PackBaggage(const IAttributeDictionaryPtr& baggage)
SetBaggage(baggage ? ConvertToYsonString(baggage) : TYsonString{});
}
-void TTraceContext::AddTag(const TString& tagKey, const TString& tagValue)
+void TTraceContext::AddTag(const std::string& tagKey, const std::string& tagValue)
{
if (!IsRecorded()) {
return;
@@ -483,19 +464,19 @@ void TTraceContext::AddTag(const TString& tagKey, const TString& tagValue)
Tags_.emplace_back(tagKey, tagValue);
}
-void TTraceContext::AddProfilingTag(const TString& name, const TString& value)
+void TTraceContext::AddProfilingTag(const std::string& name, const std::string& value)
{
auto guard = Guard(Lock_);
ProfilingTags_.emplace_back(name, value);
}
-void TTraceContext::AddProfilingTag(const TString& name, i64 value)
+void TTraceContext::AddProfilingTag(const std::string& name, i64 value)
{
auto guard = Guard(Lock_);
ProfilingTags_.emplace_back(name, value);
}
-std::vector<std::pair<TString, std::variant<TString, i64>>> TTraceContext::GetProfilingTags()
+std::vector<std::pair<std::string, std::variant<std::string, i64>>> TTraceContext::GetProfilingTags()
{
auto guard = Guard(Lock_);
return ProfilingTags_;
@@ -654,7 +635,7 @@ void ToProto(NProto::TTracingExt* ext, const TTraceContextPtr& context)
}
}
-TTraceContextPtr TTraceContext::NewRoot(TString spanName, TTraceId traceId)
+TTraceContextPtr TTraceContext::NewRoot(const std::string& spanName, TTraceId traceId)
{
return New<TTraceContext>(
TSpanContext{
@@ -663,18 +644,18 @@ TTraceContextPtr TTraceContext::NewRoot(TString spanName, TTraceId traceId)
.Sampled = false,
.Debug = false,
},
- std::move(spanName));
+ spanName);
}
TTraceContextPtr TTraceContext::NewChildFromSpan(
TSpanContext parentSpanContext,
- TString spanName,
+ const std::string& spanName,
std::optional<TString> endpoint,
TYsonString baggage)
{
auto result = New<TTraceContext>(
parentSpanContext,
- std::move(spanName));
+ spanName);
result->SetBaggage(std::move(baggage));
result->SetTargetEndpoint(endpoint);
return result;
@@ -682,7 +663,7 @@ TTraceContextPtr TTraceContext::NewChildFromSpan(
TTraceContextPtr TTraceContext::NewChildFromRpc(
const NProto::TTracingExt& ext,
- TString spanName,
+ const std::string& spanName,
TRequestId requestId,
bool forceTracing)
{
@@ -692,7 +673,7 @@ TTraceContextPtr TTraceContext::NewChildFromRpc(
return nullptr;
}
- auto root = NewRoot(std::move(spanName));
+ auto root = NewRoot(spanName);
root->SetRequestId(requestId);
root->SetRecorded();
return root;
@@ -705,7 +686,7 @@ TTraceContextPtr TTraceContext::NewChildFromRpc(
ext.sampled(),
ext.debug()
},
- std::move(spanName));
+ spanName);
traceContext->SetRequestId(requestId);
if (ext.has_baggage()) {
traceContext->SetBaggage(TYsonString(ext.baggage()));
@@ -800,7 +781,7 @@ void* AcquireFiberTagStorage()
return reinterpret_cast<void*>(traceContext);
}
-std::vector<std::pair<TString, std::variant<TString, i64>>> ReadFiberTags(void* storage)
+std::vector<std::pair<std::string, NTracing::TTraceContext::TProfilingTagValue>> ReadFiberTags(void* storage)
{
if (auto* traceContext = reinterpret_cast<NTracing::TTraceContext*>(storage)) {
return traceContext->GetProfilingTags();
diff --git a/yt/yt/core/tracing/trace_context.h b/yt/yt/core/tracing/trace_context.h
index 1a1b70f3ea..8bdf90aabd 100644
--- a/yt/yt/core/tracing/trace_context.h
+++ b/yt/yt/core/tracing/trace_context.h
@@ -15,6 +15,8 @@
#include <library/cpp/yt/threading/rw_spin_lock.h>
#include <library/cpp/yt/threading/spin_lock.h>
+#include <library/cpp/yt/memory/atomic_intrusive_ptr.h>
+
#include <atomic>
namespace NYT::NTracing {
@@ -127,21 +129,17 @@ public:
void SetRequestId(TRequestId requestId);
TRequestId GetRequestId() const;
- void SetAllocationTags(TAllocationTags::TTags&& tags);
- TAllocationTags::TTags GetAllocationTags() const;
+ TAllocationTags GetAllocationTags() const;
+ void SetAllocationTags(TAllocationTags&& tags);
- TAllocationTagsPtr GetAllocationTagsPtr() const noexcept;
- void SetAllocationTagsPtr(TAllocationTagsPtr allocationTags) noexcept;
- void ClearAllocationTagsPtr() noexcept;
+ TAllocationTagListPtr GetAllocationTagList() const noexcept;
+ void SetAllocationTagList(TAllocationTagListPtr list) noexcept;
- template <typename TTag>
- std::optional<TTag> FindAllocationTag(const TString& key) const;
- template <typename TTag>
- std::optional<TTag> SetAllocationTag(
- const TString& key,
- TTag value);
- template <typename TTag>
- std::optional<TTag> RemoveAllocationTag(const TString& key);
+ template <typename T>
+ std::optional<T> FindAllocationTag(const TAllocationTagKey& key) const;
+ template <typename T>
+ std::optional<T> SetAllocationTag(const TAllocationTagKey& key, const T& value);
+ void RemoveAllocationTag(const TAllocationTagKey& key);
//! Sets logging tag.
/*!
@@ -158,7 +156,7 @@ public:
*/
TDuration GetDuration() const;
- using TTagList = TCompactVector<std::pair<TString, TString>, 4>;
+ using TTagList = TCompactVector<std::pair<std::string, std::string>, 4>;
TTagList GetTags() const;
NYson::TYsonString GetBaggage() const;
@@ -167,10 +165,10 @@ public:
NYTree::IAttributeDictionaryPtr UnpackOrCreateBaggage() const;
void PackBaggage(const NYTree::IAttributeDictionaryPtr& baggage);
- void AddTag(const TString& tagKey, const TString& tagValue);
+ void AddTag(const std::string& tagKey, const std::string& tagValue);
template <class T>
- void AddTag(const TString& tagName, const T& tagValue);
+ void AddTag(const std::string& tagName, const T& tagValue);
//! Adds error tag. Spans containing errors are highlighted in tracing UI.
void AddErrorTag();
@@ -192,27 +190,29 @@ public:
NProfiling::TCpuDuration GetElapsedCpuTime() const;
TDuration GetElapsedTime() const;
- static TTraceContextPtr NewRoot(TString spanName, TTraceId traceId = {});
+ static TTraceContextPtr NewRoot(const std::string& spanName, TTraceId traceId = {});
static TTraceContextPtr NewChildFromRpc(
const NProto::TTracingExt& ext,
- TString spanName,
+ const std::string& spanName,
TRequestId requestId = {},
bool forceTracing = false);
static TTraceContextPtr NewChildFromSpan(
TSpanContext parentSpanContext,
- TString spanName,
+ const std::string& spanName,
std::optional<TString> endpoint = {},
NYson::TYsonString baggage = NYson::TYsonString());
TTraceContextPtr CreateChild(
- TString spanName,
+ const std::string& spanName,
std::optional<NProfiling::TCpuInstant> startTime = {});
- void AddProfilingTag(const TString& name, const TString& value);
- void AddProfilingTag(const TString& name, i64 value);
- std::vector<std::pair<TString, std::variant<TString, i64>>> GetProfilingTags();
+ void AddProfilingTag(const std::string& name, const std::string& value);
+ void AddProfilingTag(const std::string& name, i64 value);
+
+ using TProfilingTagValue = std::variant<std::string, i64>;
+ std::vector<std::pair<std::string, TProfilingTagValue>> GetProfilingTags();
friend void ToProto(NProto::TTracingExt* ext, const TTraceContextPtr& context);
@@ -244,29 +244,20 @@ private:
TAsyncChildrenList AsyncChildren_;
NYson::TYsonString Baggage_;
- std::vector<std::pair<TString, std::variant<TString, i64>>> ProfilingTags_;
+ std::vector<std::pair<std::string, TProfilingTagValue>> ProfilingTags_;
- // Must NOT allocate memory on the heap in callbacks with modifying AllocationTags_ to avoid deadlock with allocator.
- YT_DECLARE_SPIN_LOCK(NThreading::TReaderWriterSpinLock, AllocationTagsLock_);
- YT_DECLARE_SPIN_LOCK(NThreading::TSpinLock, AllocationTagsAsRefCountedLock_);
- TAllocationTagsPtr AllocationTags_;
+ // Must NOT allocate memory while modifying AllocationTagList_ to avoid deadlock with allocator.
+ YT_DECLARE_SPIN_LOCK(NThreading::TSpinLock, AllocationTagsLock_);
+ TAtomicIntrusivePtr<TAllocationTagList> AllocationTagList_;
TTraceContext(
TSpanContext parentSpanContext,
- TString spanName,
+ const std::string& spanName,
TTraceContextPtr parentTraceContext = nullptr,
std::optional<NProfiling::TCpuInstant> startTime = {});
DECLARE_NEW_FRIEND()
- void DoSetAllocationTags(TAllocationTags::TTags&& tags);
-
- template <typename TTag>
- std::optional<TTag> DoSetAllocationTag(const TString& key, TTag newTag);
-
- TAllocationTags::TTags DoGetAllocationTags() const;
-
- template <typename TTag>
- std::optional<TTag> DoFindAllocationTag(const TString& key) const;
+ void DoSetAllocationTags(TAllocationTags&& tags);
void SubmitToTracer(const ITracerPtr& tracer);
};
@@ -292,7 +283,7 @@ TTraceContext* TryGetTraceContextFromPropagatingStorage(const NConcurrency::TPro
//! Creates a new trace context. If the current trace context exists, it becomes the parent of the
//! created trace context.
-TTraceContextPtr CreateTraceContextFromCurrent(TString spanName);
+TTraceContextPtr CreateTraceContextFromCurrent(const std::string& spanName);
////////////////////////////////////////////////////////////////////////////////
@@ -384,10 +375,10 @@ class TChildTraceContextGuard
public:
TChildTraceContextGuard(
const TTraceContextPtr& traceContext,
- TString spanName,
+ const std::string& spanName,
std::optional<NProfiling::TCpuInstant> startTime = {});
explicit TChildTraceContextGuard(
- TString spanName,
+ const std::string& spanName,
std::optional<NProfiling::TCpuInstant> startTime = {});
TChildTraceContextGuard(TChildTraceContextGuard&& other) = default;
diff --git a/yt/yt/core/tracing/unittests/allocation_tags_ut.cpp b/yt/yt/core/tracing/unittests/allocation_tags_ut.cpp
index 9be4ebb8a8..9c567309ee 100644
--- a/yt/yt/core/tracing/unittests/allocation_tags_ut.cpp
+++ b/yt/yt/core/tracing/unittests/allocation_tags_ut.cpp
@@ -13,26 +13,26 @@ TEST(TAllocationTagsTest, GetSetAllocationTags)
auto traceContext = TTraceContext::NewRoot("Root");
TTraceContextGuard guard(traceContext);
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("a"), std::nullopt);
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("a"), std::nullopt);
traceContext->SetAllocationTags({{"user", "first"}, {"sometag", "my"}});
ASSERT_EQ(traceContext->FindAllocationTag<TMemoryTag>("memory_tag"), std::nullopt);
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("user"), "first");
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("sometag"), "my");
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("other"), std::nullopt);
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("user"), "first");
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("sometag"), "my");
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("other"), std::nullopt);
ASSERT_EQ(traceContext->FindAllocationTag<int>("other"), std::nullopt);
- traceContext->SetAllocationTag<TString>("a", "e");
+ traceContext->SetAllocationTag<std::string>("a", "e");
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("a"), "e");
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("a"), "e");
- traceContext->RemoveAllocationTag<TString>("a");
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("a"), std::nullopt);
+ traceContext->RemoveAllocationTag("a");
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("a"), std::nullopt);
- traceContext->RemoveAllocationTag<TString>("user");
- traceContext->RemoveAllocationTag<TString>("sometag");
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("user"), std::nullopt);
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("sometag"), std::nullopt);
+ traceContext->RemoveAllocationTag("user");
+ traceContext->RemoveAllocationTag("sometag");
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("user"), std::nullopt);
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("sometag"), std::nullopt);
ASSERT_TRUE(traceContext->GetAllocationTags().empty());
traceContext->SetAllocationTag<TMemoryTag>("memory_tag", TMemoryTag{1});
diff --git a/yt/yt/core/ya.make b/yt/yt/core/ya.make
index fd9f4b0792..c2c3ccd3ed 100644
--- a/yt/yt/core/ya.make
+++ b/yt/yt/core/ya.make
@@ -225,7 +225,6 @@ SRCS(
threading/spin_wait_slow_path_logger.cpp
threading/thread.cpp
- GLOBAL tracing/allocation_hooks.cpp
tracing/allocation_tags.cpp
tracing/config.cpp
tracing/public.cpp
@@ -308,6 +307,12 @@ SRCS(
ytalloc/statistics_producer.cpp
)
+IF (OS_LINUX)
+ SRCS(
+ GLOBAL tracing/allocation_tags_hooks.cpp
+ )
+ENDIF()
+
IF (OS_LINUX OR OS_FREEBSD)
EXTRALIBS(-lutil)
ENDIF()
diff --git a/yt/yt/library/tracing/jaeger/tracer.cpp b/yt/yt/library/tracing/jaeger/tracer.cpp
index c3b254e7b5..1a8ab4e81e 100644
--- a/yt/yt/library/tracing/jaeger/tracer.cpp
+++ b/yt/yt/library/tracing/jaeger/tracer.cpp
@@ -168,6 +168,8 @@ void ToProtoUInt64(TString* proto, i64 i)
void ToProto(NProto::Span* proto, const TTraceContextPtr& traceContext)
{
+ using NYT::ToProto;
+
ToProtoGuid(proto->mutable_trace_id(), traceContext->GetTraceId());
ToProtoUInt64(proto->mutable_span_id(), traceContext->GetSpanId());
@@ -182,8 +184,8 @@ void ToProto(NProto::Span* proto, const TTraceContextPtr& traceContext)
for (const auto& [name, value] : traceContext->GetTags()) {
auto* protoTag = proto->add_tags();
- protoTag->set_key(name);
- protoTag->set_v_str(value);
+ protoTag->set_key(ToProto<TProtobufString>(name));
+ protoTag->set_v_str(ToProto<TProtobufString>(value));
}
for (const auto& logEntry : traceContext->GetLogEntries()) {
diff --git a/yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.cpp b/yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.cpp
index 9586d7292c..f79052d105 100644
--- a/yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.cpp
+++ b/yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.cpp
@@ -22,17 +22,17 @@ class TAllocationTagProfiler
{
public:
TAllocationTagProfiler(
- std::vector<TString> tagNames,
+ std::vector<TAllocationTagKey> tagKeys,
IInvokerPtr invoker,
std::optional<TDuration> updatePeriod,
std::optional<i64> samplingRate,
NProfiling::TProfiler profiler)
: Profiler_(std::move(profiler))
- , TagNames_(std::move(tagNames))
+ , TagKeys_(std::move(tagKeys))
, UpdateExecutor_(New<TPeriodicExecutor>(
std::move(invoker),
BIND(&TAllocationTagProfiler::UpdateGauges, MakeWeak(this)),
- std::move(updatePeriod)))
+ updatePeriod))
{
if (samplingRate) {
tcmalloc::MallocExtension::SetProfileSamplingRate(*samplingRate);
@@ -43,35 +43,35 @@ public:
private:
const NProfiling::TProfiler Profiler_;
- const std::vector<TString> TagNames_;
+ const std::vector<TAllocationTagKey> TagKeys_;
const NConcurrency::TPeriodicExecutorPtr UpdateExecutor_;
- THashMap<TString, THashMap<TString, NProfiling::TGauge>> HeapUsageByType_;
+ THashMap<TAllocationTagKey, THashMap<TAllocationTagValue, NProfiling::TGauge>> Guages_;
void UpdateGauges()
{
- auto memorySnapshot = GetMemoryUsageSnapshot();
- YT_VERIFY(memorySnapshot);
+ auto memorySnapshot = GetGlobalMemoryUsageSnapshot();
- for (const auto& tagName : TagNames_) {
- auto& heapUsageMap = HeapUsageByType_.emplace(tagName, THashMap<TString, TGauge>{}).first->second;
- const auto& snapshotSlice = memorySnapshot->GetUsage(tagName);
+ for (const auto& tagKey : TagKeys_) {
+ auto& guages = Guages_.emplace(tagKey, THashMap<TAllocationTagValue, TGauge>{}).first->second;
+ const auto& slice = memorySnapshot->GetUsageSlice(tagKey);
- for (auto& [tagValue, gauge] : heapUsageMap) {
- if (auto it = snapshotSlice.find(tagValue)) {
+ for (auto& [tagValue, gauge] : guages) {
+ if (auto it = slice.find(tagValue)) {
gauge.Update(it->second);
} else {
gauge.Update(0.0);
}
}
- for (const auto& [tagValue, usage] : snapshotSlice) {
- auto it = heapUsageMap.find(tagValue);
- if (it == heapUsageMap.end()) {
- it = heapUsageMap.emplace(tagValue, Profiler_
- .WithTag(tagName, tagValue)
- .Gauge(Format("/%v", NYPath::ToYPathLiteral(tagName))))
+ for (const auto& [tagValue, usage] : slice) {
+ auto it = guages.find(tagValue);
+ if (it == guages.end()) {
+ it = guages.emplace(tagValue, Profiler_
+ // TODO(babenko): migrate to std::string
+ .WithTag(TString(tagKey), TString(tagValue))
+ .Gauge(Format("/%v", NYPath::ToYPathLiteral(tagKey))))
.first;
it->second.Update(usage);
}
@@ -95,14 +95,14 @@ public:
////////////////////////////////////////////////////////////////////////////////
IAllocationTagProfilerPtr CreateAllocationTagProfiler(
- std::vector<TString> tagNames,
+ std::vector<TAllocationTagKey> tagKeys,
IInvokerPtr invoker,
std::optional<TDuration> updatePeriod,
std::optional<i64> samplingRate,
NYT::NProfiling::TProfiler profiler)
{
return New<TAllocationTagProfiler>(
- std::move(tagNames),
+ std::move(tagKeys),
std::move(invoker),
std::move(updatePeriod),
std::move(samplingRate),
diff --git a/yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.h b/yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.h
index 9db2c37312..18c4c904d4 100644
--- a/yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.h
+++ b/yt/yt/library/ytprof/allocation_tag_profiler/allocation_tag_profiler.h
@@ -25,7 +25,7 @@ DEFINE_REFCOUNTED_TYPE(IAllocationTagProfiler);
////////////////////////////////////////////////////////////////////////////////
IAllocationTagProfilerPtr CreateAllocationTagProfiler(
- std::vector<TString> tagNames,
+ std::vector<TAllocationTagKey> tagKeys,
IInvokerPtr invoker,
std::optional<TDuration> updatePeriod,
std::optional<i64> samplingRate,
diff --git a/yt/yt/library/ytprof/api/api.h b/yt/yt/library/ytprof/api/api.h
index c04b1ebcf5..854e2ab7fe 100644
--- a/yt/yt/library/ytprof/api/api.h
+++ b/yt/yt/library/ytprof/api/api.h
@@ -41,7 +41,7 @@ std::array<TAtomicSignalPtr<TProfilerTag>, MaxActiveTags>* GetCpuProfilerTags();
// Hooks for yt/yt/core fibers.
void* AcquireFiberTagStorage();
-std::vector<std::pair<TString, std::variant<TString, i64>>> ReadFiberTags(void* storage);
+std::vector<std::pair<std::string, std::variant<std::string, i64>>> ReadFiberTags(void* storage);
void ReleaseFiberTagStorage(void* storage);
TCpuInstant GetTraceContextTimingCheckpoint();
diff --git a/yt/yt/library/ytprof/cpu_profiler.cpp b/yt/yt/library/ytprof/cpu_profiler.cpp
index 3e64ea3836..3fd656c056 100644
--- a/yt/yt/library/ytprof/cpu_profiler.cpp
+++ b/yt/yt/library/ytprof/cpu_profiler.cpp
@@ -22,7 +22,7 @@ namespace NYT::NYTProf {
////////////////////////////////////////////////////////////////////////////////
-#if not defined(_linux_)
+#if !defined(_linux_)
TCpuProfiler::TCpuProfiler(TCpuProfilerOptions options)
: TSignalSafeProfiler(options)
@@ -37,7 +37,7 @@ void TCpuProfiler::EnableProfiler()
void TCpuProfiler::DisableProfiler()
{ }
-void TCpuProfiler::AnnotateProfile(NProto::Profile* /* profile */, const std::function<i64(const TString&)>& /* stringify */)
+void TCpuProfiler::AnnotateProfile(NProto::Profile* /*profile*/, const TStringify& /*stringify*/)
{ }
i64 TCpuProfiler::EncodeValue(i64 value)
@@ -136,7 +136,7 @@ void TCpuProfiler::DisableProfiler()
}
}
-void TCpuProfiler::AnnotateProfile(NProto::Profile* profile, const std::function<i64(const TString&)>& stringify)
+void TCpuProfiler::AnnotateProfile(NProto::Profile* profile, const TStringify& stringify)
{
auto sampleType = profile->add_sample_type();
sampleType->set_type(stringify("sample"));
diff --git a/yt/yt/library/ytprof/cpu_profiler.h b/yt/yt/library/ytprof/cpu_profiler.h
index cd98012d83..08982f2920 100644
--- a/yt/yt/library/ytprof/cpu_profiler.h
+++ b/yt/yt/library/ytprof/cpu_profiler.h
@@ -58,7 +58,7 @@ private:
void EnableProfiler() override;
void DisableProfiler() override;
- void AnnotateProfile(NProto::Profile* profile, const std::function<i64(const TString&)>& stringify) override;
+ void AnnotateProfile(NProto::Profile* profile, const TStringify& stringify) override;
i64 EncodeValue(i64 value) override;
};
diff --git a/yt/yt/library/ytprof/heap_profiler.cpp b/yt/yt/library/ytprof/heap_profiler.cpp
index 822b96ffc2..9168d929a8 100644
--- a/yt/yt/library/ytprof/heap_profiler.cpp
+++ b/yt/yt/library/ytprof/heap_profiler.cpp
@@ -4,59 +4,21 @@
#include <library/cpp/yt/backtrace/cursors/libunwind/libunwind_cursor.h>
+#include <yt/yt/core/misc/protobuf_helpers.h>
+
+#include <library/cpp/yt/memory/allocation_tags_hooks.h>
#include <library/cpp/yt/memory/atomic_intrusive_ptr.h>
#include <library/cpp/yt/memory/leaky_singleton.h>
#include <library/cpp/yt/memory/new.h>
-#include <library/cpp/yt/threading/rw_spin_lock.h>
-
-#include <util/generic/hash_set.h>
#include <util/string/join.h>
-#include <util/string/cast.h>
-#include <tcmalloc/malloc_extension.h>
+#include <util/system/thread.h>
+#include <mutex>
#include <thread>
-namespace NYT {
-
-////////////////////////////////////////////////////////////////////////////////
-
-Y_WEAK void* CreateAllocationTagsData()
-{
- return nullptr;
-}
-
-Y_WEAK void* CopyAllocationTagsData(void* userData)
-{
- return userData;
-}
-
-Y_WEAK void DestroyAllocationTagsData(void* /*userData*/)
-{ }
-
-Y_WEAK const std::vector<std::pair<TString, TString>>* ReadAllocationTagsData(void* /*userData*/)
-{
- return nullptr;
-}
-
-Y_WEAK std::optional<TString> FindTagValue(
- const std::vector<std::pair<TString, TString>>& tags,
- const TString& key)
-{
- Y_UNUSED(tags);
- Y_UNUSED(key);
- return ::ToString(NullMemoryTag);
-}
-
-Y_WEAK void StartAllocationTagsCleanupThread(TDuration /*cleanupInterval*/)
-{ }
-
-////////////////////////////////////////////////////////////////////////////////
-
-namespace NYTProf {
-
-using namespace NThreading;
+namespace NYT::NYTProf {
////////////////////////////////////////////////////////////////////////////////
@@ -65,25 +27,29 @@ NProto::Profile ConvertAllocationProfile(const tcmalloc::Profile& snapshot)
NProto::Profile profile;
profile.add_string_table();
- auto addString = [&] (TString str) {
+ auto addString = [&] (const std::string& str) {
auto index = profile.string_table_size();
- profile.add_string_table(str);
+ profile.add_string_table(ToProto<TProtobufString>(str));
return index;
};
- auto sampleType = profile.add_sample_type();
- sampleType->set_type(addString("allocations"));
- sampleType->set_unit(addString("count"));
+ auto bytesUnitId = addString("bytes");
- sampleType = profile.add_sample_type();
- sampleType->set_type(addString("space"));
+ {
+ auto* sampleType = profile.add_sample_type();
+ sampleType->set_type(addString("allocations"));
+ sampleType->set_unit(addString("count"));
+ }
- auto bytesUnitId = addString("bytes");
- sampleType->set_unit(bytesUnitId);
+ {
+ auto* sampleType = profile.add_sample_type();
+ sampleType->set_type(addString("space"));
+ sampleType->set_unit(bytesUnitId);
- auto periodType = profile.mutable_period_type();
- periodType->set_type(sampleType->type());
- periodType->set_unit(sampleType->unit());
+ auto* periodType = profile.mutable_period_type();
+ periodType->set_type(sampleType->type());
+ periodType->set_unit(sampleType->unit());
+ }
profile.set_period(snapshot.Period());
@@ -93,21 +59,21 @@ NProto::Profile ConvertAllocationProfile(const tcmalloc::Profile& snapshot)
THashMap<void*, ui64> locations;
snapshot.Iterate([&] (const tcmalloc::Profile::Sample& sample) {
- auto sampleProto = profile.add_sample();
- sampleProto->add_value(sample.count);
- sampleProto->add_value(sample.sum);
+ auto* protoSample = profile.add_sample();
+ protoSample->add_value(sample.count);
+ protoSample->add_value(sample.sum);
- auto allocatedSizeLabel = sampleProto->add_label();
+ auto* allocatedSizeLabel = protoSample->add_label();
allocatedSizeLabel->set_key(allocatedSizeId);
allocatedSizeLabel->set_num(sample.allocated_size);
allocatedSizeLabel->set_num_unit(bytesUnitId);
- auto requestedSizeLabel = sampleProto->add_label();
+ auto* requestedSizeLabel = protoSample->add_label();
requestedSizeLabel->set_key(requestedSizeId);
requestedSizeLabel->set_num(sample.requested_size);
requestedSizeLabel->set_num_unit(bytesUnitId);
- auto requestedAlignmentLabel = sampleProto->add_label();
+ auto* requestedAlignmentLabel = protoSample->add_label();
requestedAlignmentLabel->set_key(requestedAlignmentId);
requestedAlignmentLabel->set_num(sample.requested_alignment);
requestedAlignmentLabel->set_num_unit(bytesUnitId);
@@ -117,27 +83,25 @@ NProto::Profile ConvertAllocationProfile(const tcmalloc::Profile& snapshot)
auto it = locations.find(ip);
if (it != locations.end()) {
- sampleProto->add_location_id(it->second);
+ protoSample->add_location_id(it->second);
continue;
}
auto locationId = locations.size() + 1;
- auto location = profile.add_location();
+ auto* location = profile.add_location();
location->set_address(reinterpret_cast<ui64>(ip));
location->set_id(locationId);
- sampleProto->add_location_id(locationId);
+ protoSample->add_location_id(locationId);
locations[ip] = locationId;
}
// TODO(gepardo): Deduplicate values in string table
- if (const auto* data = ReadAllocationTagsData(sample.user_data)) {
- for (const auto& [key, value] : *data) {
- auto label = sampleProto->add_label();
- label->set_key(addString(key));
- label->set_str(addString(value));
- }
+ for (const auto& [key, value] : GetAllocationTagsHooks().ReadAllocationTags(sample.user_data)) {
+ auto* label = protoSample->add_label();
+ label->set_key(addString(key));
+ label->set_str(addString(value));
}
});
@@ -158,23 +122,55 @@ NProto::Profile ReadHeapProfile(tcmalloc::ProfileType profileType)
return ConvertAllocationProfile(snapshot);
}
+int AbslStackUnwinder(
+ void** frames,
+ int* /*framesSizes*/,
+ int maxFrames,
+ int skipFrames,
+ const void* /*uc*/,
+ int* /*minDroppedFrames*/)
+{
+ NBacktrace::TLibunwindCursor cursor;
+
+ for (int i = 0; i < skipFrames + 1; ++i) {
+ cursor.MoveNext();
+ }
+
+ int count = 0;
+ for (int i = 0; i < maxFrames; ++i) {
+ if (cursor.IsFinished()) {
+ return count;
+ }
+
+ // IP point's to return address. Subtract 1 to get accurate line information for profiler.
+ frames[i] = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(cursor.GetCurrentIP()) - 1);
+ count++;
+
+ cursor.MoveNext();
+ }
+ return count;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
TMemoryUsageSnapshot::TMemoryUsageSnapshot(TMemoryUsageSnapshot::TData&& data) noexcept
: Data_(std::move(data))
{ }
-const THashMap<TString, size_t>& TMemoryUsageSnapshot::GetUsage(const TString& tagName) const noexcept
+const THashMap<TAllocationTagValue, size_t>& TMemoryUsageSnapshot::GetUsageSlice(const TAllocationTagKey& key) const noexcept
{
- if (auto it = Data_.find(tagName)) {
+ if (auto it = Data_.find(key)) {
return it->second;
}
- return EmptyHashMap_;
+ static const THashMap<TAllocationTagValue, size_t> empty;
+ return empty;
}
-size_t TMemoryUsageSnapshot::GetUsage(const TString& tagName, const TString& tag) const noexcept
+size_t TMemoryUsageSnapshot::GetUsage(const TAllocationTagKey& key, const TAllocationTagKey& value) const noexcept
{
- if (auto it = Data_.find(tagName)) {
- if (auto usageIt = it->second.find(tag)) {
+ if (auto it = Data_.find(key)) {
+ if (auto usageIt = it->second.find(value)) {
return usageIt->second;
}
}
@@ -184,8 +180,13 @@ size_t TMemoryUsageSnapshot::GetUsage(const TString& tagName, const TString& tag
////////////////////////////////////////////////////////////////////////////////
-struct TMemoryUsageSnapshotStorage
+struct TGlobalMemoryUsageSnapshot
{
+ static TGlobalMemoryUsageSnapshot* Get()
+ {
+ return LeakySingleton<TGlobalMemoryUsageSnapshot>();
+ }
+
TAtomicIntrusivePtr<TMemoryUsageSnapshot> Snapshot{New<TMemoryUsageSnapshot>()};
};
@@ -195,85 +196,51 @@ TMemoryUsageSnapshotPtr CollectMemoryUsageSnapshot()
auto snapshot = tcmalloc::MallocExtension::SnapshotCurrent(tcmalloc::ProfileType::kHeap);
snapshot.Iterate([&] (const tcmalloc::Profile::Sample& sample) {
- if (const auto* data = ReadAllocationTagsData(sample.user_data)) {
- for (const auto& [tagName, tag] : *data) {
- usage[tagName][tag] += sample.sum;
- }
+ for (const auto& [tagKey, tagValue] : GetAllocationTagsHooks().ReadAllocationTags(sample.user_data)) {
+ usage[tagKey][tagValue] += sample.sum;
}
});
return New<TMemoryUsageSnapshot>(std::move(usage));
}
-void UpdateMemoryUsageSnapshot(TMemoryUsageSnapshotPtr usageSnapshot)
+void SetGlobalMemoryUsageSnapshot(TMemoryUsageSnapshotPtr snapshot)
{
- auto snapshot = LeakySingleton<TMemoryUsageSnapshotStorage>();
- snapshot->Snapshot.Store(std::move(usageSnapshot));
+ TGlobalMemoryUsageSnapshot::Get()->Snapshot.Store(std::move(snapshot));
}
-TMemoryUsageSnapshotPtr GetMemoryUsageSnapshot()
+TMemoryUsageSnapshotPtr GetGlobalMemoryUsageSnapshot()
{
- const auto snapshot = LeakySingleton<TMemoryUsageSnapshotStorage>();
- return snapshot->Snapshot.Acquire();
+ return TGlobalMemoryUsageSnapshot::Get()->Snapshot.Acquire();
}
-int AbslStackUnwinder(
- void** frames,
- int*,
- int maxFrames,
- int skipFrames,
- const void*,
- int*)
+void EnableMemoryProfilingTags(std::optional<TDuration> snapshotUpdatePeriod)
{
- NBacktrace::TLibunwindCursor cursor;
-
- for (int i = 0; i < skipFrames + 1; ++i) {
- cursor.MoveNext();
- }
-
- int count = 0;
- for (int i = 0; i < maxFrames; ++i) {
- if (cursor.IsFinished()) {
- return count;
- }
-
- // IP point's to return address. Subtract 1 to get accurate line information for profiler.
- frames[i] = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(cursor.GetCurrentIP()) - 1);
- count++;
-
- cursor.MoveNext();
- }
- return count;
-}
-
-void EnableMemoryProfilingTags(std::optional<TDuration> updateSnapshotPeriod)
-{
- StartAllocationTagsCleanupThread(TDuration::Seconds(1));
- tcmalloc::MallocExtension::SetSampleUserDataCallbacks(
- &CreateAllocationTagsData,
- &CopyAllocationTagsData,
- &DestroyAllocationTagsData);
-
- if (updateSnapshotPeriod) {
- std::thread backgroundThread([updateSnapshotPeriod] {
- TInstant lastUpdateTime;
- TInstant currentTime;
-
- while (true) {
- lastUpdateTime = Now();
- UpdateMemoryUsageSnapshot(CollectMemoryUsageSnapshot());
-
- currentTime = Now();
- if (lastUpdateTime + updateSnapshotPeriod.value() > currentTime) {
- Sleep(lastUpdateTime + updateSnapshotPeriod.value() - currentTime);
+ static std::once_flag onceFlag;
+ std::call_once(onceFlag, [&] {
+ const auto& hooks = GetAllocationTagsHooks();
+ tcmalloc::MallocExtension::SetSampleUserDataCallbacks(
+ hooks.CreateAllocationTags,
+ hooks.CopyAllocationTags,
+ hooks.DestroyAllocationTags);
+
+ if (snapshotUpdatePeriod) {
+ std::thread thread([snapshotUpdatePeriod] {
+ TThread::SetCurrentThreadName("MemSnapUpdate");
+ while (true) {
+ auto lastUpdateTime = Now();
+ SetGlobalMemoryUsageSnapshot(CollectMemoryUsageSnapshot());
+ auto currentTime = Now();
+ if (lastUpdateTime + *snapshotUpdatePeriod > currentTime) {
+ Sleep(lastUpdateTime + *snapshotUpdatePeriod - currentTime);
+ }
}
- }
- });
- backgroundThread.detach();
- }
+ });
+ thread.detach();
+ }
+ });
}
////////////////////////////////////////////////////////////////////////////////
-} // namespace NYTProf
-} // namespace NYT
+} // namespace NYT::NYTProf
diff --git a/yt/yt/library/ytprof/heap_profiler.h b/yt/yt/library/ytprof/heap_profiler.h
index ca2eb9ae48..faaa2d4560 100644
--- a/yt/yt/library/ytprof/heap_profiler.h
+++ b/yt/yt/library/ytprof/heap_profiler.h
@@ -6,6 +6,8 @@
#include <util/datetime/base.h>
+#include <library/cpp/yt/memory/allocation_tags.h>
+
#include <util/generic/hash.h>
#include <tcmalloc/malloc_extension.h>
@@ -15,51 +17,48 @@ namespace NYT::NYTProf {
////////////////////////////////////////////////////////////////////////////////
NProto::Profile ConvertAllocationProfile(const tcmalloc::Profile& snapshot);
-
NProto::Profile ReadHeapProfile(tcmalloc::ProfileType profileType);
-int AbslStackUnwinder(void** frames, int*,
- int maxFrames, int skipFrames,
- const void*,
- int*);
+int AbslStackUnwinder(
+ void** frames,
+ int* framesSizes,
+ int maxFrames,
+ int skipFrames,
+ const void* uc,
+ int* minDroppedFrames);
////////////////////////////////////////////////////////////////////////////////
-class TMemoryUsageSnapshot
- : public virtual TRefCounted
+class TMemoryUsageSnapshot final
{
public:
- using TData = THashMap<TString, THashMap<TString, size_t>>;
+ using TData = THashMap<TAllocationTagKey, THashMap<TAllocationTagValue, size_t>>;
TMemoryUsageSnapshot() = default;
-
- TMemoryUsageSnapshot(TMemoryUsageSnapshot&& other) noexcept = default;
-
explicit TMemoryUsageSnapshot(TData&& data) noexcept;
- const THashMap<TString, size_t>& GetUsage(const TString& tagName) const noexcept;
-
- size_t GetUsage(const TString& tagName, const TString& tag) const noexcept;
+ const THashMap<TAllocationTagKey, size_t>& GetUsageSlice(const TAllocationTagKey& key) const noexcept;
+ size_t GetUsage(const TAllocationTagKey& key, const TAllocationTagValue& value) const noexcept;
private:
const TData Data_;
- static inline const THashMap<TString, size_t> EmptyHashMap_;
};
DEFINE_REFCOUNTED_TYPE(TMemoryUsageSnapshot)
////////////////////////////////////////////////////////////////////////////////
+//! Builds the current snapshot of memory usage.
TMemoryUsageSnapshotPtr CollectMemoryUsageSnapshot();
-//! Update snapshot in LeakySingleton.
-void UpdateMemoryUsageSnapshot(TMemoryUsageSnapshotPtr usageSnapshot);
+//! Updates the global memory usage snapshot.
+void SetGlobalMemoryUsageSnapshot(TMemoryUsageSnapshotPtr snapshot);
-//! Get snapshot from LeakySingleton.
-TMemoryUsageSnapshotPtr GetMemoryUsageSnapshot();
+//! Gets the global memory usage snapshot.
+TMemoryUsageSnapshotPtr GetGlobalMemoryUsageSnapshot();
-//! If put updateSnapshotPeriod will start updating snapshot in LeakySingleton.
-void EnableMemoryProfilingTags(std::optional<TDuration> updateSnapshotPeriod = std::nullopt);
+//! If updateSnapshotPeriod is non-null, starts updating global snapshot in background thread.
+void EnableMemoryProfilingTags(std::optional<TDuration> snapshotUpdatePeriod = {});
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/library/ytprof/signal_safe_profiler.cpp b/yt/yt/library/ytprof/signal_safe_profiler.cpp
index 754ceb26c3..6a735eb26b 100644
--- a/yt/yt/library/ytprof/signal_safe_profiler.cpp
+++ b/yt/yt/library/ytprof/signal_safe_profiler.cpp
@@ -15,29 +15,28 @@
#endif
#include <yt/yt/core/misc/proc.h>
+#include "yt/yt/core/misc/protobuf_helpers.h"
#include <library/cpp/yt/cpu_clock/clock.h>
+#include <library/cpp/yt/misc/hash.h>
+
namespace NYT::NYTProf {
////////////////////////////////////////////////////////////////////////////////
TProfileLocation::operator size_t() const
{
- size_t hash = Tid;
- hash = CombineHashes(hash, std::hash<TString>()(ThreadName));
-
+ size_t hash = 0;
+ HashCombine(hash, Tid);
+ HashCombine(hash, ThreadName);
for (auto ip : Backtrace) {
- hash = CombineHashes(hash, ip);
+ HashCombine(hash, ip);
}
-
for (const auto& tag : Tags) {
- hash = CombineHashes(hash,
- CombineHashes(
- std::hash<TString>{}(tag.first),
- std::hash<std::variant<TString, i64>>{}(tag.second)));
+ HashCombine(hash, tag.first);
+ HashCombine(hash, std::hash<std::variant<std::string, i64>>()(tag.second));
}
-
return hash;
}
@@ -48,7 +47,7 @@ Y_WEAK void* AcquireFiberTagStorage()
return nullptr;
}
-Y_WEAK std::vector<std::pair<TString, std::variant<TString, i64>>> ReadFiberTags(void* /* storage */)
+Y_WEAK std::vector<std::pair<std::string, std::variant<std::string, i64>>> ReadFiberTags(void* /* storage */)
{
return {};
}
@@ -298,16 +297,15 @@ NProto::Profile TSignalSafeProfiler::ReadProfile()
NProto::Profile profile;
profile.add_string_table();
- THashMap<TString, ui64> stringTable;
- auto stringify = [&] (const TString& str) -> i64 {
+ THashMap<std::string, i64> stringTable;
+ auto stringify = [&] (const std::string& str) -> i64 {
if (auto it = stringTable.find(str); it != stringTable.end()) {
return it->second;
- } else {
- auto nameId = profile.string_table_size();
- profile.add_string_table(str);
- stringTable[str] = nameId;
- return nameId;
}
+ auto nameId = profile.string_table_size();
+ profile.add_string_table(ToProto<TProtobufString>(str));
+ stringTable[str] = nameId;
+ return nameId;
};
AnnotateProfile(&profile, stringify);
@@ -331,9 +329,9 @@ NProto::Profile TSignalSafeProfiler::ReadProfile()
auto label = sample->add_label();
label->set_key(stringify(tag.first));
- if (auto intValue = std::get_if<i64>(&tag.second)) {
+ if (auto* intValue = std::get_if<i64>(&tag.second)) {
label->set_num(*intValue);
- } else if (auto strValue = std::get_if<TString>(&tag.second)) {
+ } else if (const auto* strValue = std::get_if<std::string>(&tag.second)) {
label->set_str(stringify(*strValue));
}
}
diff --git a/yt/yt/library/ytprof/signal_safe_profiler.h b/yt/yt/library/ytprof/signal_safe_profiler.h
index e44516861c..09316039a0 100644
--- a/yt/yt/library/ytprof/signal_safe_profiler.h
+++ b/yt/yt/library/ytprof/signal_safe_profiler.h
@@ -26,7 +26,7 @@ struct TProfileLocation
{
size_t Tid = 0;
TString ThreadName;
- std::vector<std::pair<TString, std::variant<TString, i64>>> Tags;
+ std::vector<std::pair<std::string, std::variant<std::string, i64>>> Tags;
std::vector<ui64> Backtrace;
bool operator == (const TProfileLocation& other) const = default;
@@ -82,7 +82,8 @@ protected:
virtual void EnableProfiler() = 0;
virtual void DisableProfiler() = 0;
- virtual void AnnotateProfile(NProto::Profile* profile, const std::function<i64(const TString&)>& stringify) = 0;
+ using TStringify = std::function<i64(const std::string& str)>;
+ virtual void AnnotateProfile(NProto::Profile* profile, const TStringify& stringify) = 0;
virtual i64 EncodeValue(i64 value) = 0;
void RecordSample(NBacktrace::TFramePointerCursor* cursor, i64 value);
diff --git a/yt/yt/library/ytprof/spinlock_profiler.cpp b/yt/yt/library/ytprof/spinlock_profiler.cpp
index a5a03461da..87961cb359 100644
--- a/yt/yt/library/ytprof/spinlock_profiler.cpp
+++ b/yt/yt/library/ytprof/spinlock_profiler.cpp
@@ -94,7 +94,7 @@ void TSpinlockProfiler::OnEvent(const void* lock, int64_t waitCycles)
HandlingEvent_.store(false);
}
-void TSpinlockProfiler::AnnotateProfile(NProto::Profile* profile, const std::function<i64(const TString&)>& stringify)
+void TSpinlockProfiler::AnnotateProfile(NProto::Profile* profile, const TStringify& stringify)
{
auto sampleType = profile->add_sample_type();
sampleType->set_type(stringify("sample"));
@@ -118,7 +118,6 @@ i64 TSpinlockProfiler::EncodeValue(i64 value)
////////////////////////////////////////////////////////////////////////////////
-
TBlockingProfiler::TBlockingProfiler(TSpinlockProfilerOptions options)
: TSignalSafeProfiler(options)
, Options_(options)
@@ -204,7 +203,7 @@ void TBlockingProfiler::OnEvent(
HandlingEvent_.store(false);
}
-void TBlockingProfiler::AnnotateProfile(NProto::Profile* profile, const std::function<i64(const TString&)>& stringify)
+void TBlockingProfiler::AnnotateProfile(NProto::Profile* profile, const TStringify& stringify)
{
auto sampleType = profile->add_sample_type();
sampleType->set_type(stringify("sample"));
diff --git a/yt/yt/library/ytprof/spinlock_profiler.h b/yt/yt/library/ytprof/spinlock_profiler.h
index 6df576c3b7..e8aceec85a 100644
--- a/yt/yt/library/ytprof/spinlock_profiler.h
+++ b/yt/yt/library/ytprof/spinlock_profiler.h
@@ -36,7 +36,7 @@ private:
void EnableProfiler() override;
void DisableProfiler() override;
- void AnnotateProfile(NProto::Profile* profile, const std::function<i64(const TString&)>& stringify) override;
+ void AnnotateProfile(NProto::Profile* profile, const TStringify& stringify) override;
i64 EncodeValue(i64 value) override;
static void OnEvent(const void *lock, int64_t waitCycles);
@@ -63,7 +63,7 @@ private:
void EnableProfiler() override;
void DisableProfiler() override;
- void AnnotateProfile(NProto::Profile* profile, const std::function<i64(const TString&)>& stringify) override;
+ void AnnotateProfile(NProto::Profile* profile, const TStringify& stringify) override;
i64 EncodeValue(i64 value) override;
static void OnEvent(
diff --git a/yt/yt/library/ytprof/unittests/heap_profiler_ut.cpp b/yt/yt/library/ytprof/unittests/heap_profiler_ut.cpp
index 42dcf6e802..6935216130 100644
--- a/yt/yt/library/ytprof/unittests/heap_profiler_ut.cpp
+++ b/yt/yt/library/ytprof/unittests/heap_profiler_ut.cpp
@@ -33,22 +33,22 @@ using namespace NTracing;
////////////////////////////////////////////////////////////////////////////////
-constexpr auto MemoryAllocationTag = "memory_allocation_tag";
-const std::vector<TString> MemoryAllocationTags = {"0", "1", "2", "3", "4", "5", "6", "7"};
+const std::string MemoryAllocationTagKey = "memory_allocation_tag";
+const std::vector<std::string> MemoryAllocationTagValues = {"0", "1", "2", "3", "4", "5", "6", "7"};
////////////////////////////////////////////////////////////////////////////////
template <size_t Index>
Y_NO_INLINE auto BlowHeap()
{
- std::vector<TString> data;
+ std::vector<std::string> data;
for (int i = 0; i < 10240; i++) {
- data.push_back(TString(1024, 'x'));
+ data.push_back(std::string(1_KB, 'x'));
}
return data;
}
-TEST(HeapProfiler, ReadProfile)
+TEST(THeapProfilerTest, ReadProfile)
{
absl::SetStackUnwinder(AbslStackUnwinder);
tcmalloc::MallocExtension::SetProfileSamplingRate(256_KB);
@@ -56,6 +56,7 @@ TEST(HeapProfiler, ReadProfile)
auto token = tcmalloc::MallocExtension::StartAllocationProfiling();
EnableMemoryProfilingTags();
+
auto traceContext = TTraceContext::NewRoot("Root");
TTraceContextGuard guard(traceContext);
@@ -64,18 +65,18 @@ TEST(HeapProfiler, ReadProfile)
auto h0 = BlowHeap<0>();
auto tag = TMemoryTag(1);
- traceContext->SetAllocationTags({{"user", "second"}, {"sometag", "notmy"}, {MemoryAllocationTag, ToString(tag)}});
- auto currentTag = traceContext->FindAllocationTag<TMemoryTag>(MemoryAllocationTag);
+ traceContext->SetAllocationTags({{"user", "second"}, {"sometag", "notmy"}, {MemoryAllocationTagKey, ToString(tag)}});
+ auto currentTag = traceContext->FindAllocationTag<TMemoryTag>(MemoryAllocationTagKey);
ASSERT_EQ(currentTag, tag);
auto h1 = BlowHeap<1>();
- traceContext->ClearAllocationTagsPtr();
+ traceContext->SetAllocationTagList(nullptr);
auto h2 = BlowHeap<2>();
h2.clear();
- auto usage = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTag, ToString(tag));
+ auto usage = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTagKey, ToString(tag));
ASSERT_GE(usage, 5_MB);
auto dumpProfile = [] (auto name, auto type) {
@@ -98,124 +99,124 @@ TEST(HeapProfiler, ReadProfile)
output.Finish();
}
-TEST(HeapProfiler, AllocationTagsWithMemoryTag)
+TEST(THeapProfilerTest, AllocationTagsWithMemoryTag)
{
EnableMemoryProfilingTags();
auto traceContext = TTraceContext::NewRoot("Root");
TTraceContextGuard guard(traceContext);
- ASSERT_EQ(traceContext->FindAllocationTag<TString>(MemoryAllocationTag), std::nullopt);
- traceContext->SetAllocationTags({{"user", "first user"}, {MemoryAllocationTag, MemoryAllocationTags[0]}});
- ASSERT_EQ(traceContext->FindAllocationTag<TString>("user"), "first user");
- ASSERT_EQ(traceContext->FindAllocationTag<TString>(MemoryAllocationTag), MemoryAllocationTags[0]);
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>(MemoryAllocationTagKey), std::nullopt);
+ traceContext->SetAllocationTags({{"user", "first user"}, {MemoryAllocationTagKey, MemoryAllocationTagValues[0]}});
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>("user"), "first user");
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>(MemoryAllocationTagKey), MemoryAllocationTagValues[0]);
- std::vector<std::vector<TString>> heap;
+ std::vector<std::vector<std::string>> heap;
heap.push_back(BlowHeap<0>());
- traceContext->SetAllocationTags({{"user", "second user"}, {MemoryAllocationTag, MemoryAllocationTags[1]}});
- ASSERT_EQ(traceContext->FindAllocationTag<TMemoryTag>(MemoryAllocationTag), 1);
+ traceContext->SetAllocationTags({{"user", "second user"}, {MemoryAllocationTagKey, MemoryAllocationTagValues[1]}});
+ ASSERT_EQ(traceContext->FindAllocationTag<TMemoryTag>(MemoryAllocationTagKey), 1);
heap.push_back(BlowHeap<1>());
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[0]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[0]);
- auto usage1 = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTag, MemoryAllocationTags[1]);
+ auto usage1 = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTagKey, MemoryAllocationTagValues[1]);
ASSERT_NEAR(usage1, 12_MB, 8_MB);
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[2]);
- ASSERT_EQ(traceContext->FindAllocationTag<TString>(MemoryAllocationTag), MemoryAllocationTags[2]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[2]);
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>(MemoryAllocationTagKey), MemoryAllocationTagValues[2]);
{
volatile auto h = BlowHeap<2>();
}
- traceContext->ClearAllocationTagsPtr();
- ASSERT_EQ(traceContext->FindAllocationTag<TString>(MemoryAllocationTag), std::nullopt);
+ traceContext->SetAllocationTagList(nullptr);
+ ASSERT_EQ(traceContext->FindAllocationTag<std::string>(MemoryAllocationTagKey), std::nullopt);
heap.push_back(BlowHeap<0>());
{
- auto snapshot = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTag);
- ASSERT_EQ(snapshot[MemoryAllocationTags[1]], usage1);
- ASSERT_LE(snapshot[MemoryAllocationTags[2]], 1_MB);
+ auto slice = CollectMemoryUsageSnapshot()->GetUsageSlice(MemoryAllocationTagKey);
+ ASSERT_EQ(slice[MemoryAllocationTagValues[1]], usage1);
+ ASSERT_LE(slice[MemoryAllocationTagValues[2]], 1_MB);
}
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[6]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[6]);
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[3]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[3]);
heap.push_back(BlowHeap<3>());
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[4]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[4]);
heap.push_back(BlowHeap<4>());
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[7]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[7]);
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[5]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[5]);
heap.push_back(BlowHeap<5>());
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[4]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[4]);
heap.push_back(BlowHeap<4>());
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[7]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[7]);
- traceContext->SetAllocationTagsPtr(nullptr);
+ traceContext->SetAllocationTagList(nullptr);
- auto snapshot = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTag);
+ auto slice = CollectMemoryUsageSnapshot()->GetUsageSlice(MemoryAllocationTagKey);
constexpr auto maxDifference = 10_MB;
- ASSERT_NEAR(snapshot[MemoryAllocationTags[1]], snapshot[MemoryAllocationTags[3]], maxDifference);
- ASSERT_NEAR(snapshot[MemoryAllocationTags[3]], snapshot[MemoryAllocationTags[5]], maxDifference);
- ASSERT_NEAR(snapshot[MemoryAllocationTags[1]], snapshot[MemoryAllocationTags[5]], maxDifference);
+ ASSERT_NEAR(slice[MemoryAllocationTagValues[1]], slice[MemoryAllocationTagValues[3]], maxDifference);
+ ASSERT_NEAR(slice[MemoryAllocationTagValues[3]], slice[MemoryAllocationTagValues[5]], maxDifference);
+ ASSERT_NEAR(slice[MemoryAllocationTagValues[1]], slice[MemoryAllocationTagValues[5]], maxDifference);
- ASSERT_NEAR(snapshot[MemoryAllocationTags[4]], 20_MB, 15_MB);
+ ASSERT_NEAR(slice[MemoryAllocationTagValues[4]], 20_MB, 15_MB);
- ASSERT_NEAR(snapshot[MemoryAllocationTags[4]], snapshot[MemoryAllocationTags[1]] + snapshot[MemoryAllocationTags[3]], 2 * maxDifference);
- ASSERT_NEAR(snapshot[MemoryAllocationTags[4]], snapshot[MemoryAllocationTags[1]] + snapshot[MemoryAllocationTags[5]], 2 * maxDifference);
- ASSERT_NEAR(snapshot[MemoryAllocationTags[4]], snapshot[MemoryAllocationTags[3]] + snapshot[MemoryAllocationTags[5]], 2 * maxDifference);
+ ASSERT_NEAR(slice[MemoryAllocationTagValues[4]], slice[MemoryAllocationTagValues[1]] + slice[MemoryAllocationTagValues[3]], 2 * maxDifference);
+ ASSERT_NEAR(slice[MemoryAllocationTagValues[4]], slice[MemoryAllocationTagValues[1]] + slice[MemoryAllocationTagValues[5]], 2 * maxDifference);
+ ASSERT_NEAR(slice[MemoryAllocationTagValues[4]], slice[MemoryAllocationTagValues[3]] + slice[MemoryAllocationTagValues[5]], 2 * maxDifference);
- ASSERT_LE(snapshot[MemoryAllocationTags[6]], 1_MB);
- ASSERT_LE(snapshot[MemoryAllocationTags[7]], 1_MB);
+ ASSERT_LE(slice[MemoryAllocationTagValues[6]], 1_MB);
+ ASSERT_LE(slice[MemoryAllocationTagValues[7]], 1_MB);
}
template <size_t Index>
Y_NO_INLINE auto BlowHeap(int64_t megabytes)
{
- std::vector<TString> data;
+ std::vector<std::string> data;
megabytes <<= 10;
for (int64_t i = 0; i < megabytes; i++) {
- data.push_back(TString( 1024, 'x'));
+ data.push_back(std::string(1_KB, 'x'));
}
return data;
}
-TEST(HeapProfiler, HugeAllocationsTagsWithMemoryTag)
+TEST(THeapProfilerTest, HugeAllocationsTagsWithMemoryTag)
{
EnableMemoryProfilingTags();
auto traceContext = TTraceContext::NewRoot("Root");
TCurrentTraceContextGuard guard(traceContext);
- std::vector<std::vector<TString>> heap;
+ std::vector<std::vector<std::string>> heap;
heap.push_back(BlowHeap<0>());
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[1]);
- ASSERT_EQ(traceContext->FindAllocationTag<TMemoryTag>(MemoryAllocationTag), 1);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[1]);
+ ASSERT_EQ(traceContext->FindAllocationTag<TMemoryTag>(MemoryAllocationTagKey), 1);
heap.push_back(BlowHeap<1>(100));
{
- traceContext->SetAllocationTagsPtr(nullptr);
- auto usage = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTag, MemoryAllocationTags[1]);
+ traceContext->SetAllocationTagList(nullptr);
+ auto usage = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTagKey, MemoryAllocationTagValues[1]);
ASSERT_GE(usage, 100_MB);
ASSERT_LE(usage, 150_MB);
}
- traceContext->SetAllocationTag(MemoryAllocationTag, MemoryAllocationTags[2]);
+ traceContext->SetAllocationTag(MemoryAllocationTagKey, MemoryAllocationTagValues[2]);
heap.push_back(BlowHeap<1>(1000));
- traceContext->SetAllocationTagsPtr(nullptr);
- auto usage = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTag, MemoryAllocationTags[2]);
+ traceContext->SetAllocationTagList(nullptr);
+ auto usage = CollectMemoryUsageSnapshot()->GetUsage(MemoryAllocationTagKey, MemoryAllocationTagValues[2]);
ASSERT_GE(usage, 1000_MB);
ASSERT_LE(usage, 1300_MB);
}