aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbabenko <babenko@yandex-team.com>2024-12-11 12:21:17 +0300
committerbabenko <babenko@yandex-team.com>2024-12-11 12:43:16 +0300
commitc2c5fd69ceab1a54bf4b4fffedab84d9c0f3d8b3 (patch)
tree7221ee0f98e0ba77b18e1d06319f0d037cc280db
parente178160e97b929c266666b7213f74e3424e5971d (diff)
downloadydb-c2c5fd69ceab1a54bf4b4fffedab84d9c0f3d8b3.tar.gz
Polish yt/yt/library/profiling/perf
commit_hash:c87259573f6bf715aad7f33a657edacb98db967b
-rw-r--r--yt/yt/core/misc/ref_counted_tracker_profiler.cpp4
-rw-r--r--yt/yt/library/profiling/example/main.cpp10
-rw-r--r--yt/yt/library/profiling/perf/counters_other.cpp27
-rw-r--r--yt/yt/library/profiling/perf/event_counter.h (renamed from yt/yt/library/profiling/perf/counters.h)19
-rw-r--r--yt/yt/library/profiling/perf/event_counter_dummy.cpp24
-rw-r--r--yt/yt/library/profiling/perf/event_counter_linux.cpp (renamed from yt/yt/library/profiling/perf/counters.cpp)166
-rw-r--r--yt/yt/library/profiling/perf/event_counter_profiler.cpp69
-rw-r--r--yt/yt/library/profiling/perf/event_counter_profiler.h11
-rw-r--r--yt/yt/library/profiling/perf/unittests/perf_event_counter_ut.cpp (renamed from yt/yt/library/profiling/unittests/perf_counter_ut.cpp)29
-rw-r--r--yt/yt/library/profiling/perf/unittests/ya.make17
-rw-r--r--yt/yt/library/profiling/perf/ya.make8
-rw-r--r--yt/yt/library/profiling/unittests/ya.make1
-rw-r--r--yt/yt/library/program/helpers.cpp4
13 files changed, 228 insertions, 161 deletions
diff --git a/yt/yt/core/misc/ref_counted_tracker_profiler.cpp b/yt/yt/core/misc/ref_counted_tracker_profiler.cpp
index cee7477cdf0..1acf759748c 100644
--- a/yt/yt/core/misc/ref_counted_tracker_profiler.cpp
+++ b/yt/yt/core/misc/ref_counted_tracker_profiler.cpp
@@ -35,9 +35,11 @@ public:
}
};
+////////////////////////////////////////////////////////////////////////////////
+
void EnableRefCountedTrackerProfiling()
{
- LeakyRefCountedSingleton<TRefCountedTrackerProfiler>();
+ Y_UNUSED(LeakyRefCountedSingleton<TRefCountedTrackerProfiler>());
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/library/profiling/example/main.cpp b/yt/yt/library/profiling/example/main.cpp
index cb70a0775ba..06447792fe5 100644
--- a/yt/yt/library/profiling/example/main.cpp
+++ b/yt/yt/library/profiling/example/main.cpp
@@ -13,16 +13,22 @@
#include <yt/yt/core/misc/ref_counted_tracker_profiler.h>
#include <yt/yt/library/profiling/sensor.h>
+
#include <yt/yt/library/profiling/solomon/config.h>
#include <yt/yt/library/profiling/solomon/exporter.h>
#include <yt/yt/library/profiling/solomon/registry.h>
+
#include <yt/yt/library/profiling/tcmalloc/profiler.h>
-#include <yt/yt/library/profiling/perf/counters.h>
+
+#include <yt/yt/library/profiling/perf/event_counter_profiler.h>
#include <util/stream/output.h>
#include <util/system/compiler.h>
+
#include <util/generic/yexception.h>
+
#include <util/string/cast.h>
+
#include <util/system/madvise.h>
using namespace NYT;
@@ -33,7 +39,7 @@ using namespace NYT::NProfiling;
int main(int argc, char* argv[])
{
EnableTCMallocProfiler();
- EnablePerfCounters();
+ EnablePerfEventCounterProfiling();
try {
if (argc != 2 && argc != 3) {
diff --git a/yt/yt/library/profiling/perf/counters_other.cpp b/yt/yt/library/profiling/perf/counters_other.cpp
deleted file mode 100644
index 190bcc0c6f1..00000000000
--- a/yt/yt/library/profiling/perf/counters_other.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "counters.h"
-
-namespace NYT::NProfiling {
-
-////////////////////////////////////////////////////////////////////////////////
-
-TPerfEventCounter::TPerfEventCounter(EPerfEventType /* type */)
-{
- Y_UNUSED(FD_);
-}
-
-TPerfEventCounter::~TPerfEventCounter()
-{ }
-
-ui64 TPerfEventCounter::Read()
-{
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-void EnablePerfCounters()
-{ }
-
-////////////////////////////////////////////////////////////////////////////////
-
-} // namespace NYT::NProfiling
diff --git a/yt/yt/library/profiling/perf/counters.h b/yt/yt/library/profiling/perf/event_counter.h
index 6c9f050d9b5..59de2d72682 100644
--- a/yt/yt/library/profiling/perf/counters.h
+++ b/yt/yt/library/profiling/perf/event_counter.h
@@ -38,24 +38,15 @@ DEFINE_ENUM(EPerfEventType,
////////////////////////////////////////////////////////////////////////////////
-class TPerfEventCounter final
+struct IPerfEventCounter
{
-public:
- explicit TPerfEventCounter(EPerfEventType type);
- ~TPerfEventCounter();
+ virtual ~IPerfEventCounter() = default;
- TPerfEventCounter(const TPerfEventCounter&) = delete;
-
- ui64 Read();
-
-private:
- int FD_ = -1;
+ //! Returns the counter increment since the last read.
+ virtual i64 Read() = 0;
};
-////////////////////////////////////////////////////////////////////////////////
-
-//! EnablePerfCounters creates selected set of perf counters.
-void EnablePerfCounters();
+std::unique_ptr<IPerfEventCounter> CreatePerfEventCounter(EPerfEventType type);
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/library/profiling/perf/event_counter_dummy.cpp b/yt/yt/library/profiling/perf/event_counter_dummy.cpp
new file mode 100644
index 00000000000..c11cff901d1
--- /dev/null
+++ b/yt/yt/library/profiling/perf/event_counter_dummy.cpp
@@ -0,0 +1,24 @@
+#include "event_counter.h"
+
+namespace NYT::NProfiling {
+
+////////////////////////////////////////////////////////////////////////////////
+
+class TPerfEventCounter
+ : public IPerfEventCounter
+{
+public:
+ virtual i64 Read() final
+ {
+ return 0;
+ }
+};
+
+std::unique_ptr<IPerfEventCounter> CreatePerfEventCounter(EPerfEventType /*type*/)
+{
+ return std::make_unique<TPerfEventCounter>();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT::NProfiling
diff --git a/yt/yt/library/profiling/perf/counters.cpp b/yt/yt/library/profiling/perf/event_counter_linux.cpp
index e5e90d4ee89..65bdc3c51ac 100644
--- a/yt/yt/library/profiling/perf/counters.cpp
+++ b/yt/yt/library/profiling/perf/event_counter_linux.cpp
@@ -1,4 +1,4 @@
-#include "counters.h"
+#include "event_counter.h"
#include <yt/yt/core/misc/proc.h>
#include <yt/yt/core/misc/error.h>
@@ -9,8 +9,6 @@
#include <library/cpp/yt/system/handle_eintr.h>
-#include <library/cpp/yt/memory/leaky_ref_counted_singleton.h>
-
#include <linux/perf_event.h>
#include <sys/syscall.h>
@@ -21,18 +19,18 @@ namespace NYT::NProfiling {
namespace {
-struct TPerfEventDescription final
+struct TPerfEventDescription
{
- int EventType;
- int EventConfig;
+ ui32 EventType;
+ ui64 EventConfig;
};
-constexpr TPerfEventDescription SoftwareEvent(int perfName) noexcept
+constexpr TPerfEventDescription SoftwareEvent(ui64 perfName) noexcept
{
return {PERF_TYPE_SOFTWARE, perfName};
}
-constexpr TPerfEventDescription HardwareEvent(int perfName) noexcept
+constexpr TPerfEventDescription HardwareEvent(ui64 perfName) noexcept
{
return {PERF_TYPE_HARDWARE, perfName};
}
@@ -60,27 +58,28 @@ TPerfEventDescription CacheEvent(
int cacheActionTypeForConfig = [&] {
switch (eventType) {
- case ECacheActionType::Load:
- return PERF_COUNT_HW_CACHE_OP_READ;
- case ECacheActionType::Store:
- return PERF_COUNT_HW_CACHE_OP_WRITE;
- default:
- YT_ABORT();
+ case ECacheActionType::Load:
+ return PERF_COUNT_HW_CACHE_OP_READ;
+ case ECacheActionType::Store:
+ return PERF_COUNT_HW_CACHE_OP_WRITE;
+ default:
+ YT_ABORT();
}
}();
int eventTypeForConfig = [&] {
switch (eventResultType) {
- case ECacheEventType::Access:
- return PERF_COUNT_HW_CACHE_RESULT_ACCESS;
- case ECacheEventType::Miss:
- return PERF_COUNT_HW_CACHE_RESULT_MISS;
- default:
- YT_ABORT();
+ case ECacheEventType::Access:
+ return PERF_COUNT_HW_CACHE_RESULT_ACCESS;
+ case ECacheEventType::Miss:
+ return PERF_COUNT_HW_CACHE_RESULT_MISS;
+ default:
+ YT_ABORT();
}
}();
- int eventConfig = (perfName << kEventNameShift) |
+ ui64 eventConfig =
+ (perfName << kEventNameShift) |
(cacheActionTypeForConfig << kCacheActionTypeShift) |
(eventTypeForConfig << kEventTypeShift);
@@ -157,94 +156,73 @@ TPerfEventDescription GetDescription(EPerfEventType type)
}
}
-int OpenPerfEvent(int tid, int eventType, int eventConfig)
-{
- perf_event_attr attr{};
-
- attr.type = eventType;
- attr.size = sizeof(attr);
- attr.config = eventConfig;
- attr.inherit = 1;
-
- int fd = HandleEintr(syscall, SYS_perf_event_open, &attr, tid, -1, -1, PERF_FLAG_FD_CLOEXEC);
- if (fd == -1) {
- THROW_ERROR_EXCEPTION("Failed to open perf event descriptor")
- << TError::FromSystem()
- << TErrorAttribute("type", eventType)
- << TErrorAttribute("config", eventConfig);
- }
- return fd;
-}
-
-ui64 FetchPerfCounter(int fd)
-{
- ui64 num{};
- if (HandleEintr(read, fd, &num, sizeof(num)) != sizeof(num)) {
- THROW_ERROR_EXCEPTION("Failed to read perf event counter")
- << TError::FromSystem();
- }
- return num;
-}
-
} // namespace
////////////////////////////////////////////////////////////////////////////////
-TPerfEventCounter::TPerfEventCounter(EPerfEventType type)
- : FD_(OpenPerfEvent(
- 0,
- GetDescription(type).EventType,
- GetDescription(type).EventConfig))
-{ }
-
-TPerfEventCounter::~TPerfEventCounter()
+class TPerfEventCounter
+ : public IPerfEventCounter
{
- if (FD_ != -1) {
- SafeClose(FD_, false);
+public:
+ explicit TPerfEventCounter(EPerfEventType type)
+ : Type_(type)
+ {
+ const auto& description = GetDescription(type);
+
+ perf_event_attr attr{};
+ attr.type = description.EventType;
+ attr.size = sizeof(attr);
+ attr.config = description.EventConfig;
+ attr.inherit = true;
+
+ FD_ = HandleEintr(
+ syscall,
+ SYS_perf_event_open,
+ &attr,
+ /*pid*/ 0,
+ /*cpu*/ -1,
+ /*group_fd*/ -1,
+ PERF_FLAG_FD_CLOEXEC);
+
+ if (FD_ == -1) {
+ THROW_ERROR_EXCEPTION("Failed to open %Qlv perf event descriptor",
+ type)
+ << TError::FromSystem();
+ }
}
-}
-
-ui64 TPerfEventCounter::Read()
-{
- return FetchPerfCounter(FD_);
-}
-////////////////////////////////////////////////////////////////////////////////
+ ~TPerfEventCounter()
+ {
+ if (FD_ != -1) {
+ SafeClose(FD_, /*ignoreBadFD*/ false);
+ }
+ }
-DECLARE_REFCOUNTED_STRUCT(TCounterOwner)
+ i64 Read() final
+ {
+ i64 result = 0;
+ if (HandleEintr(read, FD_, &result, sizeof(result)) != sizeof(result)) {
+ THROW_ERROR_EXCEPTION("Failed to read perf event counter %Qlv",
+ Type_)
+ << TError::FromSystem();
+ }
+ return result;
+ }
-struct TCounterOwner
- : public TRefCounted
-{
- std::vector<std::unique_ptr<TPerfEventCounter>> Counters;
+private:
+ const EPerfEventType Type_;
+ int FD_ = -1;
};
-DEFINE_REFCOUNTED_TYPE(TCounterOwner)
+////////////////////////////////////////////////////////////////////////////////
-void EnablePerfCounters()
+std::unique_ptr<IPerfEventCounter> CreatePerfEventCounter(EPerfEventType type)
{
- auto owner = LeakyRefCountedSingleton<TCounterOwner>();
-
- auto exportCounter = [&] (const std::string& category, const std::string& name, EPerfEventType type) {
- try {
- owner->Counters.emplace_back(new TPerfEventCounter{type});
- TProfiler{category}.AddFuncCounter(name, owner, [counter=owner->Counters.back().get()] {
- return counter->Read();
- });
- } catch (const std::exception&) {
- }
- };
+ return std::make_unique<TPerfEventCounter>(type);
+}
- exportCounter("/cpu/perf", "/cycles", EPerfEventType::CpuCycles);
- exportCounter("/cpu/perf", "/instructions", EPerfEventType::Instructions);
- exportCounter("/cpu/perf", "/branch_instructions", EPerfEventType::BranchInstructions);
- exportCounter("/cpu/perf", "/branch_misses", EPerfEventType::BranchMisses);
- exportCounter("/cpu/perf", "/context_switches", EPerfEventType::ContextSwitches);
+////////////////////////////////////////////////////////////////////////////////
- exportCounter("/memory/perf", "/page_faults", EPerfEventType::PageFaults);
- exportCounter("/memory/perf", "/minor_page_faults", EPerfEventType::MinorPageFaults);
- exportCounter("/memory/perf", "/major_page_faults", EPerfEventType::MajorPageFaults);
-}
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/library/profiling/perf/event_counter_profiler.cpp b/yt/yt/library/profiling/perf/event_counter_profiler.cpp
new file mode 100644
index 00000000000..4db34e3fe35
--- /dev/null
+++ b/yt/yt/library/profiling/perf/event_counter_profiler.cpp
@@ -0,0 +1,69 @@
+#include "event_counter_profiler.h"
+
+#include "event_counter.h"
+
+#include <yt/yt/library/profiling/producer.h>
+
+#include <library/cpp/yt/memory/leaky_ref_counted_singleton.h>
+
+#include <library/cpp/yt/containers/enum_indexed_array.h>
+
+#include <library/cpp/yt/threading/atomic_object.h>
+
+namespace NYT::NProfiling {
+
+////////////////////////////////////////////////////////////////////////////////
+
+class TPerfEventCounterProfilerImpl
+ : public ISensorProducer
+{
+public:
+ TPerfEventCounterProfilerImpl()
+ {
+ TProfiler("").AddProducer("/perf", this);
+ }
+
+private:
+ TEnumIndexedArray<EPerfEventType, NThreading::TAtomicObject<std::unique_ptr<IPerfEventCounter>>> TypeToCounter_;
+
+ IPerfEventCounter* GetCounter(EPerfEventType type)
+ {
+ return TypeToCounter_[type].Transform([&] (auto& counter) {
+ if (!counter) {
+ counter = CreatePerfEventCounter(type);
+ }
+ return counter.get();
+ });
+ }
+
+ void CollectSensors(ISensorWriter* writer) final
+ {
+ auto writeCounter = [&] (const std::string& name, EPerfEventType type) {
+ try {
+ auto value = GetCounter(type)->Read();
+ writer->AddCounter(name, value);
+ } catch (...) {
+ }
+ };
+
+ writeCounter("/cpu/cycles", EPerfEventType::CpuCycles);
+ writeCounter("/cpu/instructions", EPerfEventType::Instructions);
+ writeCounter("/cpu/branch_instructions", EPerfEventType::BranchInstructions);
+ writeCounter("/cpu/branch_misses", EPerfEventType::BranchMisses);
+ writeCounter("/cpu/context_switches", EPerfEventType::ContextSwitches);
+ writeCounter("/memory/page_faults", EPerfEventType::PageFaults);
+ writeCounter("/memory/minor_page_faults", EPerfEventType::MinorPageFaults);
+ writeCounter("/memory/major_page_faults", EPerfEventType::MajorPageFaults);
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+void EnablePerfEventCounterProfiling()
+{
+ Y_UNUSED(LeakyRefCountedSingleton<TPerfEventCounterProfilerImpl>());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT::NProfiling
diff --git a/yt/yt/library/profiling/perf/event_counter_profiler.h b/yt/yt/library/profiling/perf/event_counter_profiler.h
new file mode 100644
index 00000000000..bc5ec03ba4c
--- /dev/null
+++ b/yt/yt/library/profiling/perf/event_counter_profiler.h
@@ -0,0 +1,11 @@
+#pragma once
+
+namespace NYT::NProfiling {
+
+////////////////////////////////////////////////////////////////////////////////
+
+void EnablePerfEventCounterProfiling();
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT::NProfiling
diff --git a/yt/yt/library/profiling/unittests/perf_counter_ut.cpp b/yt/yt/library/profiling/perf/unittests/perf_event_counter_ut.cpp
index 1482f970120..71d5a616470 100644
--- a/yt/yt/library/profiling/unittests/perf_counter_ut.cpp
+++ b/yt/yt/library/profiling/perf/unittests/perf_event_counter_ut.cpp
@@ -1,11 +1,12 @@
-#include "util/system/yield.h"
#include <gtest/gtest.h>
-#include <yt/yt/library/profiling/perf/counters.h>
+#include <yt/yt/library/profiling/perf/event_counter.h>
#include <yt/yt/core/misc/error.h>
#include <yt/yt/core/misc/proc.h>
+#include <util/system/yield.h>
+
namespace NYT::NProfiling {
namespace {
@@ -21,40 +22,32 @@ void IgnorePermissionError(const TFn& fn)
if (ex.Error().FindMatching(PermissionErrorCode)) {
return;
}
-
throw;
}
}
-TEST(TPerfCounters, Cycles)
+////////////////////////////////////////////////////////////////////////////////
+
+TEST(TPerfEventCounterTest, CpuCycles)
{
IgnorePermissionError([&] {
- TPerfEventCounter counter(EPerfEventType::CpuCycles);
- ASSERT_GE(counter.Read(), 0u);
+ ASSERT_GE(ReadPerfEventCounter(EPerfEventType::CpuCycles), 0);
});
}
-TEST(TPerfCounters, ContextSwitches)
+TEST(TPerfEventCounterTest, ContextSwitches)
{
IgnorePermissionError([&] {
- TPerfEventCounter counter(EPerfEventType::ContextSwitches);
-
for (int i = 0; i < 10; i++) {
SchedYield();
}
-
- ASSERT_GE(counter.Read(), 0u);
+ ASSERT_GE(ReadPerfEventCounter(EPerfEventType::ContextSwitches), 0);
});
}
-TEST(TPerfCounters, CounterError)
+TEST(TPerfEventCounterTest, CounterError)
{
- auto createCounter = [] {
- TPerfEventCounter counter{EPerfEventType::StalledCyclesBackend};
- return 0;
- };
-
- ASSERT_THROW(createCounter(), TErrorException);
+ ASSERT_THROW(ReadPerfEventCounter(EPerfEventType::StalledCyclesBackend), TErrorException);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/yt/yt/library/profiling/perf/unittests/ya.make b/yt/yt/library/profiling/perf/unittests/ya.make
new file mode 100644
index 00000000000..fbdaa9d1cc3
--- /dev/null
+++ b/yt/yt/library/profiling/perf/unittests/ya.make
@@ -0,0 +1,17 @@
+GTEST()
+
+INCLUDE(${ARCADIA_ROOT}/yt/ya_cpp.make.inc)
+
+SRCS(
+ perf_event_counter_ut.cpp
+)
+
+INCLUDE(${ARCADIA_ROOT}/yt/opensource.inc)
+
+PEERDIR(
+ yt/yt/library/profiling/perf
+)
+
+SIZE(SMALL)
+
+END()
diff --git a/yt/yt/library/profiling/perf/ya.make b/yt/yt/library/profiling/perf/ya.make
index 0bf244fdeb3..c4efab21fd7 100644
--- a/yt/yt/library/profiling/perf/ya.make
+++ b/yt/yt/library/profiling/perf/ya.make
@@ -2,10 +2,12 @@ LIBRARY()
INCLUDE(${ARCADIA_ROOT}/yt/ya_cpp.make.inc)
+SRCS(event_counter_profiler.cpp)
+
IF (OS_LINUX)
- SRCS(counters.cpp)
+ SRCS(event_counter_linux.cpp)
ELSE()
- SRCS(counters_other.cpp)
+ SRCS(event_counter_dummy.cpp)
ENDIF()
PEERDIR(
@@ -14,3 +16,5 @@ PEERDIR(
)
END()
+
+RECURSE_FOR_TESTS(unittests)
diff --git a/yt/yt/library/profiling/unittests/ya.make b/yt/yt/library/profiling/unittests/ya.make
index 0fa5d9e6ee3..8346254671d 100644
--- a/yt/yt/library/profiling/unittests/ya.make
+++ b/yt/yt/library/profiling/unittests/ya.make
@@ -15,7 +15,6 @@ SRCS(
tag_ut.cpp
cube_ut.cpp
exporter_ut.cpp
- perf_counter_ut.cpp
)
INCLUDE(${ARCADIA_ROOT}/yt/opensource.inc)
diff --git a/yt/yt/library/program/helpers.cpp b/yt/yt/library/program/helpers.cpp
index 191a2f672bb..b46bdd9786c 100644
--- a/yt/yt/library/program/helpers.cpp
+++ b/yt/yt/library/program/helpers.cpp
@@ -12,7 +12,7 @@
#include <yt/yt/library/tracing/jaeger/tracer.h>
-#include <yt/yt/library/profiling/perf/counters.h>
+#include <yt/yt/library/profiling/perf/event_counter_profiler.h>
#include <yt/yt/library/profiling/resource_tracker/resource_tracker.h>
@@ -76,7 +76,7 @@ void ConfigureSingletons(const TSingletonsConfigPtr& config)
NTracing::SetGlobalTracer(New<NTracing::TJaegerTracer>(config->Jaeger));
- NProfiling::EnablePerfCounters();
+ NProfiling::EnablePerfEventCounterProfiling();
NTCMalloc::TTCMallocManager::Configure(config->TCMalloc);