diff --git a/include/scea/perf.hpp b/include/scea/perf.hpp deleted file mode 100644 index 7778d72..0000000 --- a/include/scea/perf.hpp +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: BSD-2-Clause -// Copyright (c) 2023. University of Texas at Austin. All rights reserved. - -#pragma once - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -class PerfEvent { -private: - int32_t fd; - int64_t count; - - static int64_t perf_event_open(struct perf_event_attr* hw_event, pid_t pid, - int32_t cpu, int32_t group_fd, - uint64_t flags) { - return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); - } - -public: - PerfEvent() : fd(-1), count(0) {} - - void setup(int64_t type, int64_t config) { - struct perf_event_attr pe; - memset(&pe, 0, sizeof(struct perf_event_attr)); - pe.type = type; - pe.size = sizeof(struct perf_event_attr); - pe.config = config; - pe.disabled = 1; - pe.exclude_kernel = 1; - pe.exclude_hv = 1; - - fd = perf_event_open(&pe, 0, -1, -1, 0); - if (fd == -1) - throw std::runtime_error(std::string("opening perf event: ") + - std::strerror(errno)); - } - - void start() { - if (fd != -1) { - ioctl(fd, PERF_EVENT_IOC_RESET, 0); - ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); - } - } - - void stop() { - if (fd != -1) { - ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); - size_t nread = read(fd, &count, sizeof(int64_t)); - assert(nread == sizeof(int64_t)); - } - } - - int64_t getCount() const { return count; } - - ~PerfEvent() { - if (fd != -1) { - close(fd); - } - } -}; - -class PerfScopeBenchmarker { -private: - std::vector events; - std::string scopeName; - -public: - explicit PerfScopeBenchmarker(const std::string& name) - : scopeName(name), events(4) { - events[0].setup(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); - events[1].setup(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); - events[2].setup(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); - events[3].setup(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); - - for (auto& event : events) { - event.start(); - } - } - - ~PerfScopeBenchmarker() { - for (auto& event : events) { - event.stop(); - } - - std::cout << "Benchmark results for " << scopeName << ":\n"; - std::cout << "Cache Misses: " << events[0].getCount() << "\n"; - std::cout << "Cache References: " << events[1].getCount() << "\n"; - std::cout << "Instructions: " << events[2].getCount() << "\n"; - std::cout << "CPU Cycles: " << events[3].getCount() << "\n"; - } -}; - -#define BENCHMARK_SCOPE(name) PerfScopeBenchmarker benchmarker##__LINE__(name) diff --git a/include/scea/stats.hpp b/include/scea/stats.hpp index 09119d0..095e5b6 100644 --- a/include/scea/stats.hpp +++ b/include/scea/stats.hpp @@ -90,6 +90,8 @@ class ScopeBenchmarker { PerfEvent cacheMissesEvent; PerfEvent cacheReferencesEvent; PerfEvent instructionsEvent; + PerfEvent minorPageFaultsEvent; + PerfEvent majorPageFaultsEvent; std::string scopeName; static uint64_t getMaxRSS() { @@ -108,11 +110,16 @@ class ScopeBenchmarker { cacheMissesEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES), cacheReferencesEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES), - instructionsEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS) { + instructionsEvent(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS), + minorPageFaultsEvent(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN), + majorPageFaultsEvent(PERF_TYPE_SOFTWARE, + PERF_COUNT_SW_PAGE_FAULTS_MAJ) { timer.start(); cacheMissesEvent.start(); cacheReferencesEvent.start(); instructionsEvent.start(); + minorPageFaultsEvent.start(); + majorPageFaultsEvent.start(); } ~ScopeBenchmarker() { @@ -120,11 +127,15 @@ class ScopeBenchmarker { cacheMissesEvent.stop(); cacheReferencesEvent.stop(); instructionsEvent.stop(); + minorPageFaultsEvent.stop(); + majorPageFaultsEvent.stop(); uint64_t cacheMisses = cacheMissesEvent.readValue(); uint64_t cacheReferences = cacheReferencesEvent.readValue(); uint64_t instructions = instructionsEvent.readValue(); uint64_t max_rss = getMaxRSS(); + uint64_t minorPageFaults = minorPageFaultsEvent.readValue(); + uint64_t majorPageFaults = majorPageFaultsEvent.readValue(); std::cout << "Benchmark results for " << scopeName << ":\n"; std::cout << "Duration: " << timer.getDurationNano() << " nanoseconds\n"; @@ -133,6 +144,8 @@ class ScopeBenchmarker { << (static_cast(cacheMisses) / cacheReferences) * 100 << "%\n"; std::cout << "Instructions: " << instructions << "\n"; + std::cout << "Minor Page Faults: " << minorPageFaults << "\n"; + std::cout << "Major Page Faults: " << majorPageFaults << "\n"; } };