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; |
88 | int getFileDescriptor() const { return FileDescriptor; } |
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 | |
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 | |