Class: PerfCounters::Measurement
- Inherits:
-
Object
- Object
- PerfCounters::Measurement
- Defined in:
- lib/perf_counters.rb,
ext/perf_counters/perf_counters.c
Instance Attribute Summary collapse
-
#disabled ⇒ Object
Returns the value of attribute disabled.
-
#events ⇒ Object
Returns the value of attribute events.
-
#exclude_hv ⇒ Object
Returns the value of attribute exclude_hv.
-
#exclude_kernel ⇒ Object
Returns the value of attribute exclude_kernel.
Instance Method Summary collapse
- #__start ⇒ Object
- #__stop ⇒ Object
-
#initialize(events: [], exclude_kernel: true, disabled: true, exclude_hv: true) ⇒ Measurement
constructor
A new instance of Measurement.
- #start ⇒ Object
- #stop ⇒ Object
Constructor Details
#initialize(events: [], exclude_kernel: true, disabled: true, exclude_hv: true) ⇒ Measurement
Returns a new instance of Measurement.
53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/perf_counters.rb', line 53 def initialize(events: [], exclude_kernel: true, disabled: true, exclude_hv: true) @events = events @exclude_kernel = exclude_kernel @disabled = disabled @exclude_hv = exclude_hv @__events = @events.flat_map do |event| [event.name, event.type, event.value] end end |
Instance Attribute Details
#disabled ⇒ Object
Returns the value of attribute disabled.
51 52 53 |
# File 'lib/perf_counters.rb', line 51 def disabled @disabled end |
#events ⇒ Object
Returns the value of attribute events.
51 52 53 |
# File 'lib/perf_counters.rb', line 51 def events @events end |
#exclude_hv ⇒ Object
Returns the value of attribute exclude_hv.
51 52 53 |
# File 'lib/perf_counters.rb', line 51 def exclude_hv @exclude_hv end |
#exclude_kernel ⇒ Object
Returns the value of attribute exclude_kernel.
51 52 53 |
# File 'lib/perf_counters.rb', line 51 def exclude_kernel @exclude_kernel end |
Instance Method Details
#__start ⇒ Object
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 |
# File 'ext/perf_counters/perf_counters.c', line 52
VALUE
measurement_start(VALUE self) {
VALUE rb_events = rb_iv_get(self, "@events");
size_t rb_events_len = RARRAY_LEN(rb_events);
struct perf_state *state;
Data_Get_Struct(self, struct perf_state, state);
state->started = 1;
state->fds = xmalloc(sizeof(int) * rb_events_len);
state->ids = xmalloc(sizeof(uint64_t) * rb_events_len);
for (unsigned int i = 0; i < rb_events_len; i++) {
VALUE rb__events = rb_iv_get(self, "@__events");
// extract type, value
VALUE type = rb_ary_entry(rb__events, (i * 3) + 1);
VALUE config = rb_ary_entry(rb__events, (i * 3) + 2);
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.type = NUM2INT(type);
pe.config = NUM2INT(config);
pe.size = sizeof(struct perf_event_attr);
pe.disabled = rb_iv_get(self, "@disabled") == Qtrue ? 1 : 0;
pe.exclude_kernel = rb_iv_get(self, "@exclude_kernel") == Qtrue ? 1 : 0;
pe.exclude_hv = rb_iv_get(self, "@exclude_hv") == Qtrue ? 1 : 0;
pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
int current_fd;
if (i == 0) {
current_fd = perf_event_open(&pe, 0, -1, -1, 0);
} else {
current_fd = perf_event_open(&pe, 0, -1, LEADER(state->fds), 0);
}
if (current_fd == -1) {
state->started = 0;
xfree(state->fds);
xfree(state->ids);
rb_raise(rb_eArgError, "perf_event_open failed type=%d, config=%d. Check "
"your Linux kernel's version source code to see "
"if this event exists in "
"'include/uapi/linux/perf_event.h'",
NUM2INT(type), NUM2INT(config));
}
state->fds[i] = current_fd;
RAISE_ON_ERROR(ioctl(current_fd, PERF_EVENT_IOC_ID, &state->ids[i]));
}
RAISE_ON_ERROR(
ioctl(LEADER(state->fds), PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP));
RAISE_ON_ERROR(
ioctl(LEADER(state->fds), PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP));
return Qtrue;
}
|
#__stop ⇒ Object
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 |
# File 'ext/perf_counters/perf_counters.c', line 109
VALUE
measurement_stop(VALUE self) {
struct perf_state *state;
Data_Get_Struct(self, struct perf_state, state);
if (!state->started) {
return Qnil;
}
VALUE rb_events = rb_iv_get(self, "@events");
size_t rb_events_len = RARRAY_LEN(rb_events);
// TODO: check the buffer size is ok
size_t buffer_size =
(sizeof(uint64_t) + (sizeof(uint64_t) * 2 * rb_events_len));
char buffer[buffer_size];
memset(buffer, 0, buffer_size);
struct read_format *rf = (struct read_format *)buffer;
RAISE_ON_ERROR(
ioctl(LEADER(state->fds), PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP));
ssize_t read_bytes = read(LEADER(state->fds), buffer, sizeof(buffer));
for (unsigned int i = 0; i < rb_events_len; i++) {
close(state->fds[i]);
}
xfree(state->fds);
xfree(state->ids);
if (read_bytes == -1) {
rb_raise(rb_eArgError, "read of the performance counters failed");
return Qnil;
}
VALUE rb_array_result = rb_ary_new();
// Assuming here that the events are in the same order they are requested
for (unsigned int i = 0; i < rb_events_len; i++) {
rb_ary_push(rb_array_result, INT2NUM(rf->values[i].value));
}
state->started = 0;
return rb_array_result;
}
|
#start ⇒ Object
65 66 67 |
# File 'lib/perf_counters.rb', line 65 def start __start end |
#stop ⇒ Object
69 70 71 72 73 74 75 |
# File 'lib/perf_counters.rb', line 69 def stop return nil unless result_array = __stop result_array.each_with_object({}).with_index do |(result, final), i| final[events[i].name] = result end end |