From dec071829d843ebaea87d596948212d9c1133a50 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 27 Mar 2023 17:05:05 +0200 Subject: [PATCH] blinktree: Implemented performance counter interface for Genode. --- .../src/app/blinktree/benchmark/chronometer.h | 16 +--- repos/mml/src/app/blinktree/benchmark/perf.h | 82 ++++++++++++------- 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/repos/mml/src/app/blinktree/benchmark/chronometer.h b/repos/mml/src/app/blinktree/benchmark/chronometer.h index 6c6d88a234..7b725251ed 100644 --- a/repos/mml/src/app/blinktree/benchmark/chronometer.h +++ b/repos/mml/src/app/blinktree/benchmark/chronometer.h @@ -1,8 +1,6 @@ #pragma once -#ifdef PERF_SUPPORT #include "perf.h" -#endif #include "phase.h" #include #include @@ -51,7 +49,7 @@ template class InterimResult public: InterimResult(const std::uint64_t operation_count, const P &phase, const std::uint16_t iteration, const std::uint16_t core_count, const std::chrono::milliseconds time, - /*std::vector &counter,*/ + std::vector &counter, std::unordered_map executed_tasks, std::unordered_map executed_reader_tasks, std::unordered_map executed_writer_tasks, @@ -65,12 +63,10 @@ public: _scheduled_tasks_on_core(std::move(scheduled_tasks_on_core)), _scheduled_tasks_off_core(std::move(scheduled_tasks_off_core)), _worker_fills(std::move(worker_fills)) { -#ifdef PERF_SUPPORT for (auto &c : counter) { _performance_counter.emplace_back(std::make_pair(c.name(), c.read())); } -#endif } ~InterimResult() = default; @@ -181,9 +177,7 @@ public: _current_phase = phase; _current_iteration = iteration; _core_set = core_set; -#ifdef PERF_SUPPORT _perf.start(); -#endif //_start = std::chrono::steady_clock::now(); _start = Genode::Trace::timestamp(); @@ -193,9 +187,7 @@ public: { const auto end = Genode::Trace::timestamp(); //const auto end = std::chrono::steady_clock::now(); -#ifdef PERF_SUPPORT _perf.stop(); -#endif //const auto milliseconds = std::chrono::duration_cast(end-_start); const auto milliseconds = std::chrono::milliseconds((end-_start)/2000000UL); @@ -205,7 +197,7 @@ public: _current_iteration, _core_set.size(), milliseconds, - //_perf.counter(), + _perf.counter(), statistic_map(mx::tasking::profiling::Statistic::Executed), statistic_map(mx::tasking::profiling::Statistic::ExecutedReader), statistic_map(mx::tasking::profiling::Statistic::ExecutedWriter), @@ -214,16 +206,12 @@ public: statistic_map(mx::tasking::profiling::Statistic::ScheduledOffChannel), statistic_map(mx::tasking::profiling::Statistic::Fill)}; } -#ifdef PERF_SUPPORT void add(PerfCounter &performance_counter) { _perf.add(performance_counter); } -#endif private: std::uint16_t _current_iteration{0U}; P _current_phase; mx::util::core_set _core_set; -#ifdef PERF_SUPPORT alignas(64) Perf _perf; -#endif //alignas(64) std::chrono::steady_clock::time_point _start; alignas(64) size_t _start; diff --git a/repos/mml/src/app/blinktree/benchmark/perf.h b/repos/mml/src/app/blinktree/benchmark/perf.h index 544a675fad..1e65d94202 100644 --- a/repos/mml/src/app/blinktree/benchmark/perf.h +++ b/repos/mml/src/app/blinktree/benchmark/perf.h @@ -1,12 +1,11 @@ #pragma once #include -#include #include -#include // TODO: Find Genode equivalent +#include #include -#include -#include #include +#include + /* * For more Performance Counter take a look into the Manual from Intel: @@ -28,46 +27,65 @@ namespace benchmark { class PerfCounter { public: - PerfCounter(std::string &&name, const std::uint64_t type, const std::uint64_t event_id) : _name(std::move(name)) + PerfCounter(std::string &&name, const Genode::Trace::Performance_counter::Type type, const std::uint64_t event_id, const std::uint64_t mask) : _name(std::move(name)), _type(type), _event_id(static_cast(event_id)), _mask(static_cast(mask)) { - /*std::memset(&_perf_event_attribute, 0, sizeof(perf_event_attr)); - _perf_event_attribute.type = type; - _perf_event_attribute.size = sizeof(perf_event_attr); - _perf_event_attribute.config = event_id; - _perf_event_attribute.disabled = true; - _perf_event_attribute.inherit = 1; - _perf_event_attribute.exclude_kernel = false; - _perf_event_attribute.exclude_hv = false; - _perf_event_attribute.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;*/ + } ~PerfCounter() = default; bool open() { - /*_file_descriptor = syscall(__NR_perf_event_open, &_perf_event_attribute, 0, -1, -1, 0);*/ - return _file_descriptor >= 0; + try { + _counter = Genode::Trace::Performance_counter::acquire(_type); + } catch (Genode::Trace::Pfc_no_avail) { + std::cerr << "Failed to open performance counters." << std::endl; + } + + try { + Genode::Trace::Performance_counter::setup(_counter, _event_id, _mask, (_type == Genode::Trace::Performance_counter::Type::CORE ? 0x30000 : 0x550f000000000000)); + } catch (Genode::Trace::Pfc_access_error &e) { + std::cerr << "Error while setting up performance counter: " << e.error_code() << std::endl; + } + + return _counter >= 0; } bool start() { - //ioctl(_file_descriptor, PERF_EVENT_IOC_RESET, 0); - //ioctl(_file_descriptor, PERF_EVENT_IOC_ENABLE, 0); - return ::read(_file_descriptor, &_prev, sizeof(read_format)) == sizeof(read_format); + try { + Genode::Trace::Performance_counter::start(_counter); + _prev.value = static_cast(Genode::Trace::Performance_counter::read(_counter)); + std::cout << "PMC " << _name << " prev.value=" << _prev.value << std::endl; + } + catch (Genode::Trace::Pfc_access_error &e) + { + std::cerr << "Failed to start counter: " << e.error_code() << std::endl; + } + return _prev.value >= 0; } bool stop() { - //const auto is_read = ::read(_file_descriptor, &_data, sizeof(read_format)) == sizeof(read_format); - //ioctl(_file_descriptor, PERF_EVENT_IOC_DISABLE, 0); - return false; // is_read; + try { + _data.value = Genode::Trace::Performance_counter::read(_counter); + Genode::Trace::Performance_counter::stop(_counter); + Genode::Trace::Performance_counter::reset(_counter); + std::cout << "PMC " << _name << " data.value=" << _data.value << std::endl; + } + catch (Genode::Trace::Pfc_access_error &e) + { + std::cerr << "Failed to stop counter: " << e.error_code() << std::endl; + } + // const auto is_read = ::read(_file_descriptor, &_data, sizeof(read_format)) == sizeof(read_format); + // ioctl(_file_descriptor, PERF_EVENT_IOC_DISABLE, 0); + return _data.value >= 0; // is_read; } [[nodiscard]] double read() const { - const auto multiplexing_correction = static_cast(_data.time_enabled - _prev.time_enabled) / - static_cast(_data.time_running - _prev.time_running); - return static_cast(_data.value - _prev.value) * multiplexing_correction; + std::cout << "PMC " << _name << " value: " << (_data.value - _prev.value) << std::endl; + return static_cast(_data.value - _prev.value); } [[nodiscard]] const std::string &name() const { return _name; } @@ -84,8 +102,10 @@ private: }; const std::string _name; - std::int32_t _file_descriptor = -1; - //perf_event_attr _perf_event_attribute{}; + Genode::Trace::Performance_counter::Type _type; + Genode::uint64_t _event_id; + Genode::uint64_t _mask; + Genode::Trace::Performance_counter::Counter _counter; read_format _prev{}; read_format _data{}; }; @@ -101,11 +121,11 @@ public: [[maybe_unused]] static PerfCounter L1_MISSES; [[maybe_unused]] [[maybe_unused]] static PerfCounter LLC_MISSES; [[maybe_unused]] static PerfCounter LLC_REFERENCES; - [[maybe_unused]] static PerfCounter STALLED_CYCLES_BACKEND; - [[maybe_unused]] static PerfCounter STALLS_MEM_ANY; + //[[maybe_unused]] static PerfCounter STALLED_CYCLES_BACKEND; + //[[maybe_unused]] static PerfCounter STALLS_MEM_ANY; [[maybe_unused]] static PerfCounter SW_PREFETCH_ACCESS_NTA; - [[maybe_unused]] static PerfCounter SW_PREFETCH_ACCESS_T0; - [[maybe_unused]] static PerfCounter SW_PREFETCH_ACCESS_T1_T2; + //[[maybe_unused]] static PerfCounter SW_PREFETCH_ACCESS_T0; + //[[maybe_unused]] static PerfCounter SW_PREFETCH_ACCESS_T1_T2; [[maybe_unused]] static PerfCounter SW_PREFETCH_ACCESS_WRITE; Perf() noexcept = default;