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