6 #ifndef INTELLISTREAM_INCLUDE_UTILS_THREADPERF_H_
7 #define INTELLISTREAM_INCLUDE_UTILS_THREADPERF_H_
19 #include <sys/syscall.h>
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
25 #include <linux/perf_event.h>
31 #define PERF_ERROR(n) printf(n)
39 COUNT_SW_CPU_CLOCK = 0,
40 COUNT_SW_TASK_CLOCK = 1,
41 COUNT_SW_CONTEXT_SWITCHES = 2,
42 COUNT_SW_CPU_MIGRATIONS = 3,
43 COUNT_SW_PAGE_FAULTS = 4,
44 COUNT_SW_PAGE_FAULTS_MIN = 5,
45 COUNT_SW_PAGE_FAULTS_MAJ = 6,
48 COUNT_HW_CPU_CYCLES = 7,
49 COUNT_HW_INSTRUCTIONS = 8,
50 COUNT_HW_CACHE_REFERENCES = 9,
51 COUNT_HW_CACHE_MISSES = 10,
52 COUNT_HW_BRANCH_INSTRUCTIONS = 11,
53 COUNT_HW_BRANCH_MISSES = 12,
54 COUNT_HW_BUS_CYCLES = 13,
59 COUNT_HW_CACHE_L1D_LOADS = 14,
60 COUNT_HW_CACHE_L1D_LOADS_MISSES = 15,
61 COUNT_HW_CACHE_L1D_STORES = 16,
62 COUNT_HW_CACHE_L1D_STORES_MISSES = 17,
63 COUNT_HW_CACHE_L1D_PREFETCHES = 18,
66 COUNT_HW_CACHE_L1I_LOADS = 19,
67 COUNT_HW_CACHE_L1I_LOADS_MISSES = 20,
70 COUNT_HW_CACHE_LL_LOADS = 21,
71 COUNT_HW_CACHE_LL_LOADS_MISSES = 22,
72 COUNT_HW_CACHE_LL_STORES = 23,
73 COUNT_HW_CACHE_LL_STORES_MISSES = 24,
76 COUNT_HW_CACHE_DTLB_LOADS = 25,
77 COUNT_HW_CACHE_DTLB_LOADS_MISSES = 26,
78 COUNT_HW_CACHE_DTLB_STORES = 27,
79 COUNT_HW_CACHE_DTLB_STORES_MISSES = 28,
82 COUNT_HW_CACHE_ITLB_LOADS = 29,
83 COUNT_HW_CACHE_ITLB_LOADS_MISSES = 30,
86 COUNT_HW_CACHE_BPU_LOADS = 31,
87 COUNT_HW_CACHE_BPU_LOADS_MISSES = 32,
121 PerfPair(
int _ref, std::string _name) {
140 PerfEntry() { addressable =
false; }
144 std::vector<PerfEntry> entries;
148 #define LIBPERF_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
154 {.type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_CLOCK},
155 {.type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK},
156 {.type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES},
157 {.type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS},
158 {.type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS},
159 {.type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS_MIN},
160 {.type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS_MAJ},
161 {.type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES},
162 {.type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS},
163 {.type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_REFERENCES},
164 {.type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CACHE_MISSES},
165 {.type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS},
166 {.type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES},
167 {.type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BUS_CYCLES},
169 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_L1D | (PERF_COUNT_HW_CACHE_OP_READ << 8)
170 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
172 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_L1D | (PERF_COUNT_HW_CACHE_OP_READ << 8)
173 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
175 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_L1D | (PERF_COUNT_HW_CACHE_OP_WRITE << 8)
176 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
178 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_L1D | (PERF_COUNT_HW_CACHE_OP_WRITE << 8)
179 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
181 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_L1D | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8)
182 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
184 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_L1I | (PERF_COUNT_HW_CACHE_OP_READ << 8)
185 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
187 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_L1I | (PERF_COUNT_HW_CACHE_OP_READ << 8)
188 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
190 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_LL | (PERF_COUNT_HW_CACHE_OP_READ << 8)
191 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
193 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_LL | (PERF_COUNT_HW_CACHE_OP_READ << 8)
194 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
196 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_LL | (PERF_COUNT_HW_CACHE_OP_WRITE << 8)
197 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
199 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_LL | (PERF_COUNT_HW_CACHE_OP_WRITE << 8)
200 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
202 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_DTLB | (PERF_COUNT_HW_CACHE_OP_READ << 8)
203 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
205 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_DTLB | (PERF_COUNT_HW_CACHE_OP_READ << 8)
206 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
208 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_DTLB | (PERF_COUNT_HW_CACHE_OP_WRITE << 8)
209 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
211 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_DTLB | (PERF_COUNT_HW_CACHE_OP_WRITE << 8)
212 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
214 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_ITLB | (PERF_COUNT_HW_CACHE_OP_READ << 8)
215 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
217 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_ITLB | (PERF_COUNT_HW_CACHE_OP_READ << 8)
218 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))},
220 {.type = PERF_TYPE_HW_CACHE, .config = (PERF_COUNT_HW_CACHE_BPU | (PERF_COUNT_HW_CACHE_OP_READ << 8)
221 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))},
225 sys_perf_event_open(
struct perf_event_attr *hw_event,
226 pid_t pid,
int cpu,
int group_fd,
227 unsigned long flags) {
228 return syscall(__NR_perf_event_open, hw_event, pid, cpu,
241 if (pid == -1) { pid = gettid(); }
244 int nr_counters = 32;
245 for (
int i = 0; i < nr_counters; i++) {
248 entry.fds = sys_perf_event_open(&
default_attrs[i], pid, cpu, -1, 0);
250 entry.addressable =
false;
252 entry.addressable =
true;
253 ioctl(entry.fds, PERF_EVENT_IOC_DISABLE);
254 ioctl(entry.fds, PERF_EVENT_IOC_RESET);
256 entries.push_back(entry);
260 for (
size_t i = 0; i < entries.size(); i++) {
261 if (entries[i].addressable ==
true) {
262 close(entries[i].fds);
268 uint64_t readPerf(
size_t ch) {
269 if (ch > entries.size()) {
272 if (entries[ch].addressable ==
false) {
276 int ru = read(entries[ch].fds, &value,
sizeof(uint64_t));
278 PERF_ERROR(
"invalid read");
283 int startPerf(
size_t ch) {
284 ioctl(entries[ch].fds, PERF_EVENT_IOC_ENABLE);
288 int stopPerf(
size_t ch) {
289 if (ch > entries.size()) {
292 if (entries[ch].addressable ==
false) {
295 ioctl(entries[ch].fds, PERF_EVENT_IOC_DISABLE);
296 ioctl(entries[ch].fds, PERF_EVENT_IOC_RESET);
300 bool isValidChannel(
size_t ch) {
301 if (ch > entries.size()) {
304 return entries[ch].addressable;
307 typedef std::shared_ptr<PerfTool> PerfToolPtr;
308 std::string getChValueAsString(
size_t idx);
315 struct timeval tstart, tend;
324 myTool = std::make_shared<PerfTool>(0, cpu);
332 pairs.push_back(
PerfPair(COUNT_HW_INSTRUCTIONS,
"instructions"));
333 pairs.push_back(
PerfPair(COUNT_HW_CACHE_REFERENCES,
"cacheRefs"));
334 pairs.push_back(
PerfPair(COUNT_HW_CACHE_MISSES,
"cacheMiss"));
344 for (
size_t i = 0; i <
pairs.size(); i++) {
345 myTool->startPerf(
pairs[i].ref);
347 gettimeofday(&tstart, NULL);
353 gettimeofday(&tend, NULL);
354 for (
size_t i = 0; i <
pairs.size(); i++) {
355 pairs[i].record = myTool->readPerf(
pairs[i].ref);
356 myTool->stopPerf(
pairs[i].ref);
365 if (idx >
pairs.size()) {
368 size_t ch =
pairs[idx].ref;
369 if (myTool->isValidChannel(ch) ==
false) {
372 return pairs[idx].record;
380 for (
size_t i = 0; i <
pairs.size(); i++) {
381 if (
pairs[i].name == name) {
382 return pairs[i].record;
394 for (
size_t i = 0; i <
pairs.size(); i++) {
395 ru->edit(
pairs[i].name, (uint64_t)
pairs[i].record);
perfTrace
The low level description of perf events, used inside, don't touch me UNLESS you know what you are do...
Definition: ThreadPerf.hpp:37
a record pair of perf events
Definition: ThreadPerf.hpp:116
The top entity to provide perf traces, please use this class only UNLESS you know what you are doing.
Definition: ThreadPerf.hpp:109
void start()
To start perf tracing.
Definition: ThreadPerf.hpp:343
virtual void setPerfList()
To set up all your interest perf events.
Definition: ThreadPerf.hpp:330
void end()
To end a perf tracing.
Definition: ThreadPerf.hpp:352
std::vector< PerfPair > pairs
To contain all of your interested perf events.
Definition: ThreadPerf.hpp:314
ConfigMapPtr resultToConfigMap()
convert the perf result into a ConfigMap
Definition: ThreadPerf.hpp:392
ThreadPerf(int cpu)
To setup this perf to specific cpu.
Definition: ThreadPerf.hpp:323
uint64_t getResultById(size_t idx)
Get the perf result by its index of PerfPair.
Definition: ThreadPerf.hpp:364
uint64_t getResultByName(string name)
Get the perf result by its name of of PerfPair.
Definition: ThreadPerf.hpp:379
#define newConfigMap
(Macro) To creat a new ConfigMap under shared pointer.
Definition: ConfigMap.hpp:362
std::shared_ptr< ConfigMap > ConfigMapPtr
The class to describe a shared pointer to ConfigMap.
Definition: ConfigMap.hpp:356
The low-level perf descriptions passed to OS.