perf_counters 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6cced98e93f41c89e87acaa723bd631056953ff7
4
+ data.tar.gz: 5448721efebcf1d565d97fbcb98337cd5bb66c78
5
+ SHA512:
6
+ metadata.gz: 5d72ff056f7b7340c57ed55304edafaaf4dfdabf2e54a31c53cb95286a9cfaf8f4d42fb66e06b42a28bbfe9316b4c1356f2258d541b334d9d0c33cd3ddc2fcbb
7
+ data.tar.gz: 2143340b8ac4737835c26fc08fded05e36cf6a8e1f78d9d703b0c530982809187f1df4b013d3605513b2ec4a879b0ab968241c7e5c42feca38347e8e91847d3a
@@ -0,0 +1,14 @@
1
+ *.sw[po]
2
+ /.bundle/
3
+ /.yardoc
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in perf_counters.gemspec
6
+ gemspec
@@ -0,0 +1,33 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ perf_counters (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ benchmark-ips (2.7.2)
10
+ kalibera (0.1)
11
+ memoist (~> 0.11.0)
12
+ rbzip2 (~> 0.2.0)
13
+ memoist (0.11.0)
14
+ minitest (5.10.3)
15
+ rake (10.5.0)
16
+ rake-compiler (1.0.4)
17
+ rake
18
+ rbzip2 (0.2.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ benchmark-ips (~> 2.7.2)
25
+ bundler (~> 1.16)
26
+ kalibera
27
+ minitest (~> 5.0)
28
+ perf_counters!
29
+ rake (~> 10.0)
30
+ rake-compiler
31
+
32
+ BUNDLED WITH
33
+ 1.16.0
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 TODO: Write your name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ # PerfCounters
2
+
3
+ Experimental, do not use in production, could blow up your Rubies.
4
+
5
+ ### What
6
+ Read the CPU's performance counters from Ruby using `perf_event_open(2)`.
7
+
8
+ ### Usage
9
+ ```ruby
10
+ require 'perf_counters'
11
+ events = [
12
+ Event::INSTRUCTIONS,
13
+ Event::CPU_CYCLES,
14
+ Event::CACHE_MISSES,
15
+ ]
16
+ perf = PerfCounters::Measurement.new(
17
+ exclude_kernel: true,
18
+ events: events,
19
+ )
20
+ perf.start
21
+ # do something here
22
+ perf.stop
23
+ => {:instructions=>3276, :cpu_cycles=>18651, :cache_misses=>24}
24
+ ```
25
+
26
+ ### Contributing
27
+
28
+ #### Requirements
29
+ A modern Linux machine (unfortunately, most VMs don't virtualize perf counters)
30
+ with `perf` installed.
31
+
32
+ #### Install
33
+ ```shell
34
+ $ bin/setup
35
+ ```
36
+
37
+ #### Compile
38
+ ```shell
39
+ $ rake compile
40
+ ```
41
+
42
+ #### Run tests
43
+ ```shell
44
+ $ rake [test]
45
+ ```
@@ -0,0 +1,61 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ require 'rake/extensiontask'
11
+
12
+ task build: :compile
13
+
14
+ Rake::ExtensionTask.new('perf_counters') do |ext|
15
+ ext.lib_dir = 'lib/perf_counters'
16
+ end
17
+
18
+ task default: %i[clobber compile test]
19
+
20
+ task benchmark: %i[clobber compile] do
21
+ require 'benchmark/ips'
22
+ require 'perf_counters'
23
+
24
+ # TODO:
25
+ # - `x.stats = :bootstrap` seems to get frozen
26
+ # - investigate why results are not very consistent
27
+ Benchmark.ips do |x|
28
+ x.iterations = 3
29
+
30
+ x.report('no perf_counters') do |times|
31
+ (0..times).inject(:+)
32
+ end
33
+
34
+ x.report('using yield') do |times|
35
+ PerfCounters.measure(events: [Event::INSTRUCTIONS]) do
36
+ (0..times).inject(:+)
37
+ end
38
+ end
39
+
40
+ x.report('using yield (frozen array)') do |times|
41
+ PerfCounters.measure(events: [Event::INSTRUCTIONS].freeze) do
42
+ (0..times).inject(:+)
43
+ end
44
+ end
45
+
46
+ x.report('not using yield') do |times|
47
+ pc = PerfCounters::Measurement.new(events: [Event::INSTRUCTIONS])
48
+ pc.start
49
+ (0..times).inject(:+)
50
+ pc.stop
51
+ end
52
+
53
+ x.report('not using yield (frozen array)') do |times|
54
+ pc = PerfCounters::Measurement.new(events: [Event::INSTRUCTIONS].freeze)
55
+ pc.start
56
+ (0..times).inject(:+)
57
+ pc.stop
58
+ end
59
+ x.compare!
60
+ end
61
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'perf_counters'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ clang-format -i ext/perf_counters/*.[ch]
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ require 'mkmf'
2
+
3
+ $CFLAGS << ' -Wall -Werror -Wextra -Wshadow -Wpedantic'
4
+
5
+ $CFLAGS << if ENV['OPTIMIZE']
6
+ ' -O3'
7
+ else
8
+ ' -O0 -ggdb'
9
+ end
10
+
11
+ # RbConfig::MAKEFILE_CONFIG['CC'] = 'clang' if ENV['USE_CLANG']
12
+ create_makefile('perf_counters/perf_counters')
@@ -0,0 +1,161 @@
1
+ #include "perf_counters.h"
2
+ #include <asm/unistd.h>
3
+ #include <errno.h>
4
+ #include <linux/perf_event.h>
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <string.h>
9
+ #include <sys/ioctl.h>
10
+ #include <unistd.h>
11
+
12
+ #define LEADER(array) (array[0])
13
+ #define RAISE_ON_ERROR(function_call) \
14
+ do { \
15
+ if (function_call == -1) { \
16
+ state->started = 0; \
17
+ xfree(state->fds); \
18
+ xfree(state->ids); \
19
+ rb_raise(rb_eArgError, "ioctl call failed in line %d with '%s'", \
20
+ __LINE__, strerror(errno)); \
21
+ } \
22
+ } while (0);
23
+
24
+ struct read_format {
25
+ uint64_t nr;
26
+ struct {
27
+ uint64_t value;
28
+ uint64_t id;
29
+ } values[];
30
+ };
31
+ struct perf_event_attr pe;
32
+ struct perf_state {
33
+ int started;
34
+ int *fds;
35
+ uint64_t *ids;
36
+ };
37
+
38
+ static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
39
+ int cpu, int group_fd, unsigned long flags) {
40
+ return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
41
+ }
42
+
43
+ void dealloc_state(struct perf_state *state) { xfree(state); }
44
+
45
+ VALUE
46
+ alloc_state(VALUE klass) {
47
+ struct perf_state *state = xmalloc(sizeof(struct perf_state));
48
+ state->started = 0;
49
+ return Data_Wrap_Struct(klass, NULL, dealloc_state, state);
50
+ }
51
+
52
+ VALUE
53
+ measurement_start(VALUE self) {
54
+ VALUE rb_events = rb_iv_get(self, "@events");
55
+ size_t rb_events_len = RARRAY_LEN(rb_events);
56
+
57
+ struct perf_state *state;
58
+ Data_Get_Struct(self, struct perf_state, state);
59
+ state->started = 1;
60
+ state->fds = xmalloc(sizeof(int) * rb_events_len);
61
+ state->ids = xmalloc(sizeof(uint64_t) * rb_events_len);
62
+
63
+ for (unsigned int i = 0; i < rb_events_len; i++) {
64
+ VALUE rb__events = rb_iv_get(self, "@__events");
65
+ // extract type, value
66
+ VALUE type = rb_ary_entry(rb__events, (i * 3) + 1);
67
+ VALUE config = rb_ary_entry(rb__events, (i * 3) + 2);
68
+
69
+ memset(&pe, 0, sizeof(struct perf_event_attr));
70
+ pe.type = NUM2INT(type);
71
+ pe.config = NUM2INT(config);
72
+ pe.size = sizeof(struct perf_event_attr);
73
+ pe.disabled = rb_iv_get(self, "@disabled") == Qtrue ? 1 : 0;
74
+ pe.exclude_kernel = rb_iv_get(self, "@exclude_kernel") == Qtrue ? 1 : 0;
75
+ pe.exclude_hv = rb_iv_get(self, "@exclude_hv") == Qtrue ? 1 : 0;
76
+ pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
77
+
78
+ int current_fd;
79
+ if (i == 0) {
80
+ current_fd = perf_event_open(&pe, 0, -1, -1, 0);
81
+ } else {
82
+ current_fd = perf_event_open(&pe, 0, -1, LEADER(state->fds), 0);
83
+ }
84
+
85
+ if (current_fd == -1) {
86
+ state->started = 0;
87
+ xfree(state->fds);
88
+ xfree(state->ids);
89
+
90
+ rb_raise(rb_eArgError, "perf_event_open failed type=%d, config=%d. Check "
91
+ "your Linux kernel's version source code to see "
92
+ "if this event exists in "
93
+ "'include/uapi/linux/perf_event.h'",
94
+ NUM2INT(type), NUM2INT(config));
95
+ }
96
+
97
+ state->fds[i] = current_fd;
98
+ RAISE_ON_ERROR(ioctl(current_fd, PERF_EVENT_IOC_ID, &state->ids[i]));
99
+ }
100
+
101
+ RAISE_ON_ERROR(
102
+ ioctl(LEADER(state->fds), PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP));
103
+ RAISE_ON_ERROR(
104
+ ioctl(LEADER(state->fds), PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP));
105
+
106
+ return Qtrue;
107
+ }
108
+
109
+ VALUE
110
+ measurement_stop(VALUE self) {
111
+ struct perf_state *state;
112
+ Data_Get_Struct(self, struct perf_state, state);
113
+
114
+ if (!state->started) {
115
+ return Qnil;
116
+ }
117
+
118
+ VALUE rb_events = rb_iv_get(self, "@events");
119
+ size_t rb_events_len = RARRAY_LEN(rb_events);
120
+ // TODO: check the buffer size is ok
121
+ size_t buffer_size =
122
+ (sizeof(uint64_t) + (sizeof(uint64_t) * 2 * rb_events_len));
123
+ char buffer[buffer_size];
124
+ memset(buffer, 0, buffer_size);
125
+ struct read_format *rf = (struct read_format *)buffer;
126
+
127
+ RAISE_ON_ERROR(
128
+ ioctl(LEADER(state->fds), PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP));
129
+ ssize_t read_bytes = read(LEADER(state->fds), buffer, sizeof(buffer));
130
+
131
+ for (unsigned int i = 0; i < rb_events_len; i++) {
132
+ close(state->fds[i]);
133
+ }
134
+ xfree(state->fds);
135
+ xfree(state->ids);
136
+
137
+ if (read_bytes == -1) {
138
+ rb_raise(rb_eArgError, "read of the performance counters failed");
139
+ return Qnil;
140
+ }
141
+
142
+ VALUE rb_array_result = rb_ary_new();
143
+
144
+ // Assuming here that the events are in the same order they are requested
145
+ for (unsigned int i = 0; i < rb_events_len; i++) {
146
+ rb_ary_push(rb_array_result, INT2NUM(rf->values[i].value));
147
+ }
148
+
149
+ state->started = 0;
150
+ return rb_array_result;
151
+ }
152
+
153
+ void Init_perf_counters(void) {
154
+ VALUE rb_mPerfCounters = rb_define_module("PerfCounters");
155
+
156
+ VALUE rb_Measurement =
157
+ rb_define_class_under(rb_mPerfCounters, "Measurement", rb_cObject);
158
+ rb_define_alloc_func(rb_Measurement, alloc_state);
159
+ rb_define_method(rb_Measurement, "__start", measurement_start, 0);
160
+ rb_define_method(rb_Measurement, "__stop", measurement_stop, 0);
161
+ }
@@ -0,0 +1,6 @@
1
+ #ifndef PERF_COUNTERS_H
2
+ #define PERF_COUNTERS_H 1
3
+
4
+ #include "ruby.h"
5
+
6
+ #endif /* PERF_COUNTERS_H */
@@ -0,0 +1,84 @@
1
+ require 'perf_counters/version'
2
+ require 'perf_counters/perf_counters'
3
+
4
+ Counter = Struct.new(:name, :type, :value)
5
+
6
+ module Event
7
+ # from linux's include/uapi/linux/perf_event.h
8
+
9
+ # `perf_type_id`
10
+ module Type
11
+ HARDWARE = 0
12
+ SOFTWARE = 1
13
+ end
14
+
15
+ # TODO: does this make more sense?
16
+ #
17
+ # class HWCounter < Counter
18
+ # def initialize(name, value)
19
+ # super(name, Type::HARDWARE, value)
20
+ # end
21
+ # end
22
+
23
+ # `perf_hw_id`
24
+ CPU_CYCLES = Counter.new(:cpu_cycles, Type::HARDWARE, 0)
25
+ INSTRUCTIONS = Counter.new(:instructions, Type::HARDWARE, 1)
26
+ CACHE_REFERENCES = Counter.new(:cache_references, Type::HARDWARE, 2)
27
+ CACHE_MISSES = Counter.new(:cache_misses, Type::HARDWARE, 3)
28
+ BRANCH_INSTRUCTIONS = Counter.new(:branch_instructions, Type::HARDWARE, 4)
29
+ BRANCH_MISSES = Counter.new(:branch_misses, Type::HARDWARE, 5)
30
+ BUS_CYCLES = Counter.new(:bus_cycles, Type::HARDWARE, 6)
31
+ STALLED_CYCLES_FRONTEND = Counter.new(:stalled_cycles_frontend, Type::HARDWARE, 7)
32
+ STALLED_CYCLES_BACKEND = Counter.new(:stalled_cycles_backend, Type::HARDWARE, 8)
33
+ REF_CPU_CYCLES = Counter.new(:ref_cpu_cycles, Type::HARDWARE, 9)
34
+
35
+ # `perf_sw_ids`
36
+ CPU_CLOCK = Counter.new(:cpu_clock, Type::SOFTWARE, 0)
37
+ TASK_CLOCK = Counter.new(:task_clock, Type::SOFTWARE, 1)
38
+ PAGE_FAULTS = Counter.new(:page_faults, Type::SOFTWARE, 2)
39
+ CONTEXT_SWITCHES = Counter.new(:context_switches, Type::SOFTWARE, 3)
40
+ CPU_MIGRATIONS = Counter.new(:cpu_migrations, Type::SOFTWARE, 4)
41
+ PAGE_FAULTS_MIN = Counter.new(:page_faults_min, Type::SOFTWARE, 5)
42
+ PAGE_FAULTS_MAJ = Counter.new(:page_faults_maj, Type::SOFTWARE, 6)
43
+ ALIGNMENT_FAULTS = Counter.new(:alignment_faults, Type::SOFTWARE, 7)
44
+ EMULATION_FAULTS = Counter.new(:emulation_faults, Type::SOFTWARE, 8)
45
+ DUMMY = Counter.new(:dummy, Type::SOFTWARE, 9)
46
+ BPF_OUTPUT = Counter.new(:bpf_output, Type::SOFTWARE, 10)
47
+ end
48
+
49
+ module PerfCounters
50
+ class Measurement
51
+ attr_accessor :events, :exclude_kernel, :disabled, :exclude_hv
52
+
53
+ def initialize(events: [], exclude_kernel: true, disabled: true, exclude_hv: true)
54
+ @events = events
55
+
56
+ @exclude_kernel = exclude_kernel
57
+ @disabled = disabled
58
+ @exclude_hv = exclude_hv
59
+
60
+ @__events = @events.flat_map do |event|
61
+ [event.name, event.type, event.value]
62
+ end
63
+ end
64
+
65
+ def start
66
+ __start
67
+ end
68
+
69
+ def stop
70
+ return nil unless result_array = __stop
71
+
72
+ result_array.each_with_object({}).with_index do |(result, final), i|
73
+ final[events[i].name] = result
74
+ end
75
+ end
76
+ end
77
+
78
+ def self.measure(*args)
79
+ perf = PerfCounters::Measurement.new(*args)
80
+ perf.start
81
+ yield
82
+ perf.stop
83
+ end
84
+ end
@@ -0,0 +1,19 @@
1
+ module PerfCounters
2
+ module AvailableCounters
3
+ module Hardware
4
+ EVENTS_SYS_PATH = '/sys/bus/event_source/devices/cpu/events/'
5
+
6
+ class << self
7
+ def all
8
+ Dir
9
+ .entries(EVENTS_SYS_PATH)
10
+ .reject { |el| ['.', '..'].include?(el) }
11
+ end
12
+
13
+ def event(event_name)
14
+ File.read("#{EVENTS_SYS_PATH}#{event_name}")
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module PerfCounters
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,32 @@
1
+
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'perf_counters/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'perf_counters'
8
+ spec.version = PerfCounters::VERSION
9
+ spec.authors = ['Javier Honduvilla Coto']
10
+ spec.email = ['javierhonduco@gmail.com']
11
+
12
+ spec.summary = "Read the CPU's performance counters perf_event_open(2)"
13
+ spec.description = spec.summary
14
+ spec.homepage = 'https://github.com/javierhonduco/ruby_perf_counters'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+
21
+ spec.bindir = 'exe'
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
24
+ spec.extensions = ['ext/perf_counters/extconf.rb']
25
+
26
+ spec.add_development_dependency 'benchmark-ips', '~> 2.7.2'
27
+ spec.add_development_dependency 'bundler', '~> 1.16'
28
+ spec.add_development_dependency 'kalibera'
29
+ spec.add_development_dependency 'minitest', '~> 5.0'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rake-compiler'
32
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: perf_counters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Javier Honduvilla Coto
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-12-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: benchmark-ips
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.7.2
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.7.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: kalibera
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake-compiler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Read the CPU's performance counters perf_event_open(2)
98
+ email:
99
+ - javierhonduco@gmail.com
100
+ executables: []
101
+ extensions:
102
+ - ext/perf_counters/extconf.rb
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - Gemfile
107
+ - Gemfile.lock
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - bin/console
112
+ - bin/format_c
113
+ - bin/setup
114
+ - ext/perf_counters/extconf.rb
115
+ - ext/perf_counters/perf_counters.c
116
+ - ext/perf_counters/perf_counters.h
117
+ - lib/perf_counters.rb
118
+ - lib/perf_counters/available_perf_counters.rb
119
+ - lib/perf_counters/version.rb
120
+ - perf_counters.gemspec
121
+ homepage: https://github.com/javierhonduco/ruby_perf_counters
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.6.8
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Read the CPU's performance counters perf_event_open(2)
145
+ test_files: []