diff options
author | babenko <babenko@yandex-team.com> | 2024-12-11 12:21:17 +0300 |
---|---|---|
committer | babenko <babenko@yandex-team.com> | 2024-12-11 12:43:16 +0300 |
commit | c2c5fd69ceab1a54bf4b4fffedab84d9c0f3d8b3 (patch) | |
tree | 7221ee0f98e0ba77b18e1d06319f0d037cc280db | |
parent | e178160e97b929c266666b7213f74e3424e5971d (diff) | |
download | ydb-c2c5fd69ceab1a54bf4b4fffedab84d9c0f3d8b3.tar.gz |
Polish yt/yt/library/profiling/perf
commit_hash:c87259573f6bf715aad7f33a657edacb98db967b
-rw-r--r-- | yt/yt/core/misc/ref_counted_tracker_profiler.cpp | 4 | ||||
-rw-r--r-- | yt/yt/library/profiling/example/main.cpp | 10 | ||||
-rw-r--r-- | yt/yt/library/profiling/perf/counters_other.cpp | 27 | ||||
-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.cpp | 24 | ||||
-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.cpp | 69 | ||||
-rw-r--r-- | yt/yt/library/profiling/perf/event_counter_profiler.h | 11 | ||||
-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.make | 17 | ||||
-rw-r--r-- | yt/yt/library/profiling/perf/ya.make | 8 | ||||
-rw-r--r-- | yt/yt/library/profiling/unittests/ya.make | 1 | ||||
-rw-r--r-- | yt/yt/library/program/helpers.cpp | 4 |
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); |