1 //===-- PerfHelper.h ------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// Helpers for measuring perf events. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_PERFHELPER_H 15 #define LLVM_TOOLS_LLVM_EXEGESIS_PERFHELPER_H 16 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/Config/config.h" 20 #include "llvm/Support/Error.h" 21 22 #include <cstdint> 23 #include <functional> 24 #include <memory> 25 26 #ifdef _MSC_VER 27 typedef int pid_t; 28 #else 29 #include <sys/types.h> 30 #endif // _MSC_VER 31 32 struct perf_event_attr; 33 34 namespace llvm { 35 namespace exegesis { 36 namespace pfm { 37 38 // Returns true on error. 39 bool pfmInitialize(); 40 void pfmTerminate(); 41 42 // Retrieves the encoding for the event described by pfm_event_string. 43 // NOTE: pfm_initialize() must be called before creating PerfEvent objects. 44 class PerfEvent { 45 public: 46 // Dummy event that does not require access to counters (for tests). 47 static const char *const DummyEventString; 48 49 // http://perfmon2.sourceforge.net/manv4/libpfm.html 50 // Events are expressed as strings. e.g. "INSTRUCTION_RETIRED" 51 explicit PerfEvent(StringRef PfmEventString); 52 53 PerfEvent(const PerfEvent &) = delete; 54 PerfEvent(PerfEvent &&other); 55 ~PerfEvent(); 56 57 // The pfm_event_string passed at construction time. 58 StringRef name() const; 59 60 // Whether the event was successfully created. 61 bool valid() const; 62 63 // The encoded event to be passed to the Kernel. 64 const perf_event_attr *attribute() const; 65 66 // The fully qualified name for the event. 67 // e.g. "snb_ep::INSTRUCTION_RETIRED:e=0:i=0:c=0:t=0:u=1:k=0:mg=0:mh=1" 68 StringRef getPfmEventString() const; 69 70 protected: 71 PerfEvent() = default; 72 std::string EventString; 73 std::string FullQualifiedEventString; 74 perf_event_attr *Attr; 75 76 private: 77 void initRealEvent(StringRef PfmEventString); 78 }; 79 80 // Represents a single event that has been configured in the Linux perf 81 // subsystem. 82 class ConfiguredEvent { 83 public: 84 ConfiguredEvent(PerfEvent &&EventToConfigure); 85 86 void initRealEvent(const pid_t ProcessID, const int GroupFD = -1); 87 Expected<SmallVector<int64_t>> readOrError(StringRef FunctionBytes) const; getFileDescriptor()88 int getFileDescriptor() const { return FileDescriptor; } isDummyEvent()89 bool isDummyEvent() const { 90 return Event.name() == PerfEvent::DummyEventString; 91 } 92 93 ConfiguredEvent(const ConfiguredEvent &) = delete; 94 ConfiguredEvent(ConfiguredEvent &&other) = default; 95 96 ~ConfiguredEvent(); 97 98 private: 99 PerfEvent Event; 100 int FileDescriptor = -1; 101 }; 102 103 // Consists of a counter measuring a specific event and associated validation 104 // counters measuring execution conditions. All counters in a group are part 105 // of a single event group and are thus scheduled on and off the CPU as a single 106 // unit. 107 class CounterGroup { 108 public: 109 // event: the PerfEvent to measure. 110 explicit CounterGroup(PerfEvent &&event, std::vector<PerfEvent> &&ValEvents, 111 pid_t ProcessID = 0); 112 113 CounterGroup(const CounterGroup &) = delete; 114 CounterGroup(CounterGroup &&other) = default; 115 116 virtual ~CounterGroup() = default; 117 118 /// Starts the measurement of the event. 119 virtual void start(); 120 121 /// Stops the measurement of the event. 122 void stop(); 123 124 /// Returns the current value of the counter or error if it cannot be read. 125 /// FunctionBytes: The benchmark function being executed. 126 /// This is used to filter out the measurements to ensure they are only 127 /// within the benchmarked code. 128 /// If empty (or not specified), then no filtering will be done. 129 /// Not all counters choose to use this. 130 virtual Expected<SmallVector<int64_t, 4>> 131 readOrError(StringRef FunctionBytes = StringRef()) const; 132 133 virtual Expected<SmallVector<int64_t>> readValidationCountersOrError() const; 134 135 virtual int numValues() const; 136 getFileDescriptor()137 int getFileDescriptor() const { return EventCounter.getFileDescriptor(); } 138 139 protected: 140 ConfiguredEvent EventCounter; 141 bool IsDummyEvent; 142 std::vector<ConfiguredEvent> ValidationEventCounters; 143 144 private: 145 void initRealEvent(pid_t ProcessID); 146 }; 147 148 } // namespace pfm 149 } // namespace exegesis 150 } // namespace llvm 151 152 #endif // LLVM_TOOLS_LLVM_EXEGESIS_PERFHELPER_H 153