perfer 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +2 -1
- data/bin/perfer +1 -1
- data/lib/perfer.rb +1 -1
- data/lib/perfer/cli.rb +17 -1
- data/lib/perfer/formatter.rb +47 -0
- data/lib/perfer/formatter/results_formatter.rb +3 -3
- data/lib/perfer/grapher/r_grapher.rb +26 -0
- data/lib/perfer/job.rb +5 -1
- data/lib/perfer/job/input_size_job.rb +13 -10
- data/lib/perfer/job/iteration_job.rb +37 -30
- data/lib/perfer/result.rb +4 -0
- data/lib/perfer/session.rb +82 -18
- data/lib/perfer/store.rb +21 -6
- data/perfer.gemspec +1 -1
- metadata +78 -54
data/README.md
CHANGED
@@ -13,6 +13,7 @@ Commands:
|
|
13
13
|
results
|
14
14
|
path files+ - show the paths to the result files
|
15
15
|
rm,delete files+ - remove the result files
|
16
|
+
rewrite files+ - rewrite the result files in the latest format
|
16
17
|
|
17
18
|
<files+> are a set of benchmark files
|
18
19
|
|
@@ -30,4 +31,4 @@ And the [Wiki](https://github.com/jruby/perfer/wiki).
|
|
30
31
|
|
31
32
|
## Current status
|
32
33
|
|
33
|
-
This is a work in progress, 0.1.
|
34
|
+
This is a work in progress, 0.1.1 is a preview release.
|
data/bin/perfer
CHANGED
data/lib/perfer.rb
CHANGED
@@ -28,7 +28,7 @@ module Perfer
|
|
28
28
|
# Shortcut for Perfer.session { |s| s.iterate ... }
|
29
29
|
def iterate(title = nil, *args, &block)
|
30
30
|
Session.new(Path.file(caller)) { |session|
|
31
|
-
title ||= session.name
|
31
|
+
title ||= session.object.name
|
32
32
|
session.iterate(title, *args, &block)
|
33
33
|
}
|
34
34
|
end
|
data/lib/perfer/cli.rb
CHANGED
@@ -2,6 +2,7 @@ module Perfer
|
|
2
2
|
class CLI
|
3
3
|
COMMANDS = %w[
|
4
4
|
config
|
5
|
+
graph
|
5
6
|
help
|
6
7
|
report
|
7
8
|
results
|
@@ -20,6 +21,7 @@ Commands:
|
|
20
21
|
results
|
21
22
|
path files+ - show the paths to the result files
|
22
23
|
rm,delete files+ - remove the result files
|
24
|
+
rewrite files+ - rewrite the result files in the latest format
|
23
25
|
|
24
26
|
<files+> are a set of benchmark files
|
25
27
|
|
@@ -69,7 +71,7 @@ EOS
|
|
69
71
|
|
70
72
|
def report
|
71
73
|
measurements = (@argv.shift if @argv.first == '--measurements')
|
72
|
-
each_session { |session| session.
|
74
|
+
each_session { |session| session.report(:measurements => measurements) }
|
73
75
|
end
|
74
76
|
|
75
77
|
def run
|
@@ -93,6 +95,12 @@ EOS
|
|
93
95
|
end
|
94
96
|
end
|
95
97
|
|
98
|
+
def graph
|
99
|
+
each_session { |session|
|
100
|
+
session.graph
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
96
104
|
def config
|
97
105
|
case subcommand = @argv.shift
|
98
106
|
when "reset"
|
@@ -122,6 +130,14 @@ EOS
|
|
122
130
|
|
123
131
|
private
|
124
132
|
def files
|
133
|
+
# Allow common options after the command
|
134
|
+
begin
|
135
|
+
@opts.parse!(@argv)
|
136
|
+
rescue OptionParser::ParseError => e
|
137
|
+
error e.message
|
138
|
+
end
|
139
|
+
|
140
|
+
@argv = Store.all_results_paths if @argv == ['all-results']
|
125
141
|
@argv.map { |file| Path(file).expand }
|
126
142
|
end
|
127
143
|
|
data/lib/perfer/formatter.rb
CHANGED
@@ -69,5 +69,52 @@ module Perfer
|
|
69
69
|
scale = float_scale(time)
|
70
70
|
"#{format_duration(time, scale)}#{after_unit} ± #{format_error(error, time, scale)}"
|
71
71
|
end
|
72
|
+
|
73
|
+
def ruby_version(desc)
|
74
|
+
# # ruby 2.0.0dev (2012-08-25 trunk 36824) [x86_64-darwin10.8.0]
|
75
|
+
case desc
|
76
|
+
when /^ruby (\d\.\d\.\d) .+ patchlevel (\d+)/
|
77
|
+
"#{$1}p#{$2}"
|
78
|
+
when /^ruby (\d\.\d\.\d(?:p\d+|\w+)) .+ (?:trunk|revision) (\d+)/
|
79
|
+
"#{$1} r#{$2}"
|
80
|
+
when /^rubinius .+? \((\d\.\d\.\d) /
|
81
|
+
$1
|
82
|
+
when /^jruby .+? \(ruby-(\d\.\d\.\d)-p(\d+)\)/,
|
83
|
+
/^jruby .+? \((\d\.\d\.\d)p(\d+)\)/
|
84
|
+
"#{$1}p#{$2}"
|
85
|
+
when /^MacRuby .+? \(ruby (\d\.\d\.\d)\)/
|
86
|
+
$1
|
87
|
+
else
|
88
|
+
raise "Unknown ruby version: #{desc}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def short_ruby_description(desc)
|
93
|
+
impl, version = nil, nil
|
94
|
+
case desc
|
95
|
+
when /Ruby Enterprise Edition (\d{4}\.\d{2})$/
|
96
|
+
impl, version = "ree", $1
|
97
|
+
when /^MacRuby (\S+)/
|
98
|
+
impl, version = "macruby", $1
|
99
|
+
when /^rubinius (\S+) \(\d\.\d\.\d release (\d{4}-\d{2}-\d{2})/,
|
100
|
+
/^rubinius (\S+) \(\d\.\d\.\d ([0-9a-f]+) /
|
101
|
+
impl, version = "rbx", "#{$1} #{$2}"
|
102
|
+
when /^jruby (\S+) \(.+?\) \(\d{4}-\d{2}-\d{2} ([0-9a-f]+)\)/,
|
103
|
+
/^jruby (\S+) \(.+?\) (\d{4}-\d{2}-\d{2}) f+/,
|
104
|
+
/^jruby (\S+) \(.+?\) \d{4}-\d{2}-\d{2} ([0-9a-f]+)/
|
105
|
+
impl, version = "jruby", "#{$1} #{$2}"
|
106
|
+
when /^ruby /
|
107
|
+
impl = "mri"
|
108
|
+
else
|
109
|
+
raise "Unknown ruby interpreter: #{desc}"
|
110
|
+
end
|
111
|
+
ruby_version = ruby_version(desc)
|
112
|
+
|
113
|
+
if version
|
114
|
+
"#{impl} #{version} (#{ruby_version})"
|
115
|
+
else
|
116
|
+
"#{impl} #{ruby_version}"
|
117
|
+
end
|
118
|
+
end
|
72
119
|
end
|
73
120
|
end
|
@@ -17,8 +17,8 @@ module Perfer
|
|
17
17
|
result[:job].to_s.ljust(@max_job_length)
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
@
|
20
|
+
def max_input_size_length
|
21
|
+
@max_input_size_length ||= max_length_of(@results) { |r| r[:input_size] }
|
22
22
|
end
|
23
23
|
|
24
24
|
def report(options = {})
|
@@ -34,7 +34,7 @@ module Perfer
|
|
34
34
|
error /= r[:iterations]
|
35
35
|
puts "#{job_title(r)} #{format_duration_and_error time_per_i, error, '/i'} <=> #{format_ips ips} ips"
|
36
36
|
else
|
37
|
-
n = format_n(r[:
|
37
|
+
n = format_n(r[:input_size], max_input_size_length)
|
38
38
|
puts "#{job_title(r)} #{n} in #{format_duration_and_error mean, error}"
|
39
39
|
end
|
40
40
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Perfer
|
2
|
+
class RGrapher
|
3
|
+
attr_reader :r
|
4
|
+
def initialize
|
5
|
+
require 'rinruby'
|
6
|
+
@r = RinRuby.new(false, false)
|
7
|
+
end
|
8
|
+
|
9
|
+
def boxplot(results)
|
10
|
+
data = results.map { |result|
|
11
|
+
result.data.map { |m| m[:real]/result[:iterations] }
|
12
|
+
}
|
13
|
+
|
14
|
+
data.each_with_index { |d,i| r.assign("data#{i}", d) }
|
15
|
+
r.data_rownames = results.map { |result| Formatter.short_ruby_description(result[:ruby]) }
|
16
|
+
r.main_title = "#{results.first[:session]} : #{results.first[:job]}"
|
17
|
+
r.eval <<-EOR
|
18
|
+
pdf("graph.pdf", paper="a4", height=12)
|
19
|
+
data = list(#{data.size.times.map { |i| "data#{i}" } * ',' })
|
20
|
+
names(data) = data_rownames
|
21
|
+
par(mar=c(20,4,4,2), las=2, cex.axis=.8)
|
22
|
+
boxplot(data, main=main_title)
|
23
|
+
EOR
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/perfer/job.rb
CHANGED
@@ -5,8 +5,12 @@ module Perfer
|
|
5
5
|
@session = session
|
6
6
|
@title = title
|
7
7
|
@block = block
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
+
def load_metadata
|
11
|
+
@metadata = @session.metadata.merge(:job => @title)
|
12
|
+
@metadata.merge!(@session.next_job_metadata) if @session.next_job_metadata
|
13
|
+
@metadata.freeze
|
10
14
|
end
|
11
15
|
|
12
16
|
def results
|
@@ -2,12 +2,15 @@ module Perfer
|
|
2
2
|
class InputSizeJob < Job
|
3
3
|
attr_writer :last_measurement
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
end
|
5
|
+
DEFAULT_START = 1024
|
6
|
+
DEFAULT_GENERATOR = lambda { |n| n * 2 }
|
8
7
|
|
9
|
-
def
|
10
|
-
|
8
|
+
def initialize(session, title, &block)
|
9
|
+
super(session, title, &block)
|
10
|
+
extra = @session.next_job_metadata
|
11
|
+
@start = (extra && extra.delete(:start)) || DEFAULT_START
|
12
|
+
@generator = (extra && extra.delete(:generator)) || DEFAULT_GENERATOR
|
13
|
+
load_metadata
|
11
14
|
end
|
12
15
|
|
13
16
|
def measure(n)
|
@@ -18,26 +21,26 @@ module Perfer
|
|
18
21
|
|
19
22
|
def run
|
20
23
|
super
|
21
|
-
n = start
|
24
|
+
n = @start
|
22
25
|
# find an appropriate maximal n, acts as warm-up
|
23
26
|
loop do
|
24
27
|
time = measure(n)[:real]
|
25
28
|
break if time > minimal_time
|
26
|
-
n = generator(n)
|
29
|
+
n = @generator.call(n)
|
27
30
|
end
|
28
31
|
|
29
32
|
max = n
|
30
|
-
n = start
|
33
|
+
n = @start
|
31
34
|
loop do
|
32
35
|
result = Result.new(@metadata)
|
33
|
-
result[:
|
36
|
+
result[:input_size] = n
|
34
37
|
number_of_measurements.times do
|
35
38
|
result << measure(n)
|
36
39
|
end
|
37
40
|
@session.add_result(result)
|
38
41
|
|
39
42
|
break if n == max
|
40
|
-
n = generator(n)
|
43
|
+
n = @generator.call(n)
|
41
44
|
end
|
42
45
|
end
|
43
46
|
end
|
@@ -3,48 +3,52 @@ module Perfer
|
|
3
3
|
# This factor ensure some margin,
|
4
4
|
# to avoid endlessly changing the number of iterations
|
5
5
|
CHANGE_ITERATIONS_MARGIN = 0.1
|
6
|
+
MAX_GROW_FACTOR = 10
|
6
7
|
UNIQUE_NAME = "a"
|
7
8
|
|
8
9
|
def repeat_eval
|
9
10
|
100
|
10
11
|
end
|
11
12
|
|
12
|
-
def initialize(session, title, code, data, &block)
|
13
|
+
def initialize(session, title, code = nil, data = nil, &block)
|
13
14
|
super(session, title, &block)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
klass = obj.singleton_class
|
18
|
-
meth = generate_method_name
|
19
|
-
else
|
20
|
-
klass = singleton_class
|
21
|
-
meth = :measure_call_times_code
|
22
|
-
end
|
15
|
+
load_metadata
|
16
|
+
compile_method(code, data) if code and !block
|
17
|
+
end
|
23
18
|
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
def compile_method(code, data)
|
20
|
+
@data = data || {}
|
21
|
+
if obj = @data.delete(:self)
|
22
|
+
klass = obj.singleton_class
|
23
|
+
meth = generate_method_name
|
24
|
+
else
|
25
|
+
klass = singleton_class
|
26
|
+
meth = :measure_call_times_code
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
if klass.method_defined?(meth)
|
30
|
+
raise Error, "method #{meth} already defined on #{klass} (#{obj})!"
|
31
|
+
end
|
32
|
+
|
33
|
+
begin
|
34
|
+
klass.class_eval <<-EOR
|
35
|
+
def #{meth}(__n#{@data.keys.map { |k| ", #{k}" }.join})
|
36
|
+
::Perfer.measure do
|
37
|
+
__i = 0
|
38
|
+
while __i < __n
|
39
|
+
#{"#{code}; " * repeat_eval}
|
40
|
+
__i += 1
|
37
41
|
end
|
38
42
|
end
|
39
|
-
EOR
|
40
|
-
rescue SyntaxError => e
|
41
|
-
raise Error, "There was an error while eval'ing the code: #{code.inspect}\n#{e}"
|
42
43
|
end
|
44
|
+
EOR
|
45
|
+
rescue SyntaxError => e
|
46
|
+
raise Error, "There was an error while eval'ing the code: #{code.inspect}\n#{e}"
|
47
|
+
end
|
43
48
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
49
|
+
if obj
|
50
|
+
singleton_class.send(:define_method, :measure_call_times_code) do |*args|
|
51
|
+
obj.send(meth, *args)
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -78,7 +82,7 @@ module Perfer
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def compute_new_iterations(iterations, time)
|
81
|
-
(minimal_time *
|
85
|
+
(minimal_time * iterations / time).ceil
|
82
86
|
end
|
83
87
|
|
84
88
|
def find_number_of_iterations_required(last_iterations = 1, last_time = 0)
|
@@ -104,6 +108,9 @@ module Perfer
|
|
104
108
|
puts "new_iterations <= iterations: #{new_iterations} <= #{iterations}" if verbose
|
105
109
|
new_iterations = (iterations*1.5).ceil
|
106
110
|
end
|
111
|
+
if new_iterations > MAX_GROW_FACTOR * iterations
|
112
|
+
new_iterations = MAX_GROW_FACTOR * iterations
|
113
|
+
end
|
107
114
|
iterations = round_for_eval(new_iterations)
|
108
115
|
end
|
109
116
|
puts "End search for iterations: iterations=#{iterations}" if verbose
|
data/lib/perfer/result.rb
CHANGED
data/lib/perfer/session.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Perfer
|
2
2
|
class Session
|
3
|
-
attr_reader :name, :file, :jobs, :type, :
|
4
|
-
|
3
|
+
attr_reader :name, :file, :jobs, :type, :metadata, :store, :results
|
4
|
+
attr_accessor :current_job, :next_job_metadata
|
5
5
|
def initialize(file, name = nil, &block)
|
6
6
|
@file = file
|
7
7
|
@name = name || file.base.to_s
|
@@ -17,6 +17,7 @@ module Perfer
|
|
17
17
|
@jobs = []
|
18
18
|
@type = nil # will be decided by API usage (iterate/bench)
|
19
19
|
@results_to_save = []
|
20
|
+
@next_job_metadata = nil
|
20
21
|
|
21
22
|
@metadata = {
|
22
23
|
:file => @file.path,
|
@@ -30,11 +31,13 @@ module Perfer
|
|
30
31
|
add_bench_file_checksum
|
31
32
|
@metadata.freeze
|
32
33
|
|
33
|
-
yield self
|
34
|
+
yield DSL.new(self)
|
34
35
|
end
|
35
36
|
|
36
37
|
def add_config_metadata
|
37
|
-
|
38
|
+
config = Perfer.configuration.to_hash
|
39
|
+
config.delete(:verbose) # Not relevant to save
|
40
|
+
@metadata.merge!(config)
|
38
41
|
end
|
39
42
|
|
40
43
|
def add_git_metadata
|
@@ -74,27 +77,28 @@ module Perfer
|
|
74
77
|
@results_to_save.clear
|
75
78
|
end
|
76
79
|
|
77
|
-
|
78
|
-
def report_results(options = {})
|
80
|
+
def report(options = {})
|
79
81
|
load_results
|
80
82
|
SessionFormatter.new(self).report(options)
|
81
83
|
end
|
82
84
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
def graph
|
86
|
+
load_results
|
87
|
+
# consider only first job for now
|
88
|
+
last_runtime = @results.last[:runtime]
|
89
|
+
job = @results.reverse_each.take_while { |r| r[:runtime] == last_runtime }.last[:job]
|
90
|
+
data = @results.select { |r| r[:job] == job }.
|
91
|
+
sort_by { |r| r[:ruby] }.
|
92
|
+
chunk { |r| r[:ruby] }.
|
93
|
+
map { |ruby, results| results.last }
|
94
|
+
RGrapher.new.boxplot(data)
|
87
95
|
end
|
88
96
|
|
89
|
-
def
|
90
|
-
check_benchmark_type(
|
97
|
+
def add_job(job_type, title, *args, &block)
|
98
|
+
check_benchmark_type(job_type)
|
91
99
|
check_unique_job_title(title)
|
92
|
-
@jobs <<
|
93
|
-
|
94
|
-
|
95
|
-
def measure(&block)
|
96
|
-
raise Error, WRONG_MEASURE_USE unless InputSizeJob === @current_job
|
97
|
-
@current_job.last_measurement = Perfer.measure(&block)
|
100
|
+
@jobs << job_type.new(self, title, *args, &block)
|
101
|
+
@next_job_metadata = nil
|
98
102
|
end
|
99
103
|
|
100
104
|
private
|
@@ -110,5 +114,65 @@ module Perfer
|
|
110
114
|
raise Error, Errors::SAME_JOB_TITLES
|
111
115
|
end
|
112
116
|
end
|
117
|
+
|
118
|
+
class DSL
|
119
|
+
def initialize(session)
|
120
|
+
@session = session
|
121
|
+
end
|
122
|
+
|
123
|
+
def object
|
124
|
+
@session
|
125
|
+
end
|
126
|
+
|
127
|
+
def metadata(&block)
|
128
|
+
if !block
|
129
|
+
@session.metadata
|
130
|
+
else
|
131
|
+
@session.next_job_metadata = MetadataSetter.new.tap do |metadata|
|
132
|
+
metadata.instance_eval(&block)
|
133
|
+
end.to_hash
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def iterate(title, code = nil, data = nil, &block)
|
138
|
+
@session.add_job(IterationJob, title, code, data, &block)
|
139
|
+
end
|
140
|
+
|
141
|
+
def bench(title, &block)
|
142
|
+
@session.add_job(InputSizeJob, title, &block)
|
143
|
+
end
|
144
|
+
|
145
|
+
def measure(&block)
|
146
|
+
raise Error, WRONG_MEASURE_USE unless InputSizeJob === @session.current_job
|
147
|
+
@session.current_job.last_measurement = Perfer.measure(&block)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class MetadataSetter
|
152
|
+
def initialize
|
153
|
+
@metadata = {}
|
154
|
+
end
|
155
|
+
|
156
|
+
def description description
|
157
|
+
@metadata[:description] = description
|
158
|
+
end
|
159
|
+
|
160
|
+
def tags *tags
|
161
|
+
@metadata[:tags] ||= []
|
162
|
+
@metadata[:tags] |= tags.map(&:to_s)
|
163
|
+
end
|
164
|
+
|
165
|
+
def start n
|
166
|
+
@metadata[:start] = n
|
167
|
+
end
|
168
|
+
|
169
|
+
def generator &block
|
170
|
+
@metadata[:generator] = block
|
171
|
+
end
|
172
|
+
|
173
|
+
def to_hash
|
174
|
+
@metadata
|
175
|
+
end
|
176
|
+
end
|
113
177
|
end
|
114
178
|
end
|
data/lib/perfer/store.rb
CHANGED
@@ -5,18 +5,31 @@ module Perfer
|
|
5
5
|
@file = Path(file)
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.
|
9
|
-
|
8
|
+
def self.results_dir
|
9
|
+
DIR/'results'
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.all_results_paths
|
13
|
+
results_dir.glob('**/*.yml')
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.path_for_bench_file(bench_file)
|
17
|
+
path = results_dir
|
10
18
|
path.mkpath unless path.exist?
|
11
19
|
|
12
|
-
bench_file =
|
20
|
+
bench_file = Path(bench_file)
|
21
|
+
return bench_file if bench_file.inside?(results_dir)
|
13
22
|
|
14
23
|
# get the relative path to root, and relocate in @path
|
15
24
|
names = bench_file.each_filename.to_a
|
16
25
|
# prepend drive letter on Windows
|
17
26
|
names.unshift bench_file.path[0..0].upcase if File.dirname('C:') == 'C:.'
|
18
27
|
|
19
|
-
|
28
|
+
path.join(*names).add_ext('.yml')
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.for_session(session)
|
32
|
+
new path_for_bench_file(session.file)
|
20
33
|
end
|
21
34
|
|
22
35
|
def delete
|
@@ -31,7 +44,9 @@ module Perfer
|
|
31
44
|
|
32
45
|
def load
|
33
46
|
return unless @file.exist?
|
34
|
-
yaml_load_documents
|
47
|
+
yaml_load_documents.map! { |doc|
|
48
|
+
Result === doc ? doc : Result.new(doc[:metadata], doc[:data])
|
49
|
+
}
|
35
50
|
end
|
36
51
|
|
37
52
|
def append(result)
|
@@ -43,7 +58,7 @@ module Perfer
|
|
43
58
|
@file.dir.mkpath unless @file.dir.exist?
|
44
59
|
# ensure results are still ordered by :run_time
|
45
60
|
results.sort_by! { |r| r[:run_time] }
|
46
|
-
@file.write YAML.dump_stream(*results)
|
61
|
+
@file.write YAML.dump_stream(*results.map(&:to_hash))
|
47
62
|
end
|
48
63
|
|
49
64
|
def rewrite
|
data/perfer.gemspec
CHANGED
metadata
CHANGED
@@ -1,133 +1,157 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: perfer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
4
|
+
prerelease:
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- eregon
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: path
|
16
|
-
|
17
|
-
none: false
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
18
17
|
requirements:
|
19
18
|
- - ~>
|
20
19
|
- !ruby/object:Gem::Version
|
21
20
|
version: 1.3.1
|
22
|
-
type: :runtime
|
23
|
-
prerelease: false
|
24
|
-
version_requirements: !ruby/object:Gem::Requirement
|
25
21
|
none: false
|
22
|
+
requirement: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 1.3.1
|
27
|
+
none: false
|
28
|
+
prerelease: false
|
29
|
+
type: :runtime
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: ffi
|
32
|
-
|
33
|
-
none: false
|
32
|
+
version_requirements: !ruby/object:Gem::Requirement
|
34
33
|
requirements:
|
35
34
|
- - ~>
|
36
35
|
- !ruby/object:Gem::Version
|
37
36
|
version: 1.0.11
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
37
|
none: false
|
38
|
+
requirement: !ruby/object:Gem::Requirement
|
42
39
|
requirements:
|
43
40
|
- - ~>
|
44
41
|
- !ruby/object:Gem::Version
|
45
42
|
version: 1.0.11
|
43
|
+
none: false
|
44
|
+
prerelease: false
|
45
|
+
type: :runtime
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: backports
|
48
|
-
|
49
|
-
none: false
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
49
|
requirements:
|
51
50
|
- - ~>
|
52
51
|
- !ruby/object:Gem::Version
|
53
52
|
version: 2.6.3
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
53
|
none: false
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
58
55
|
requirements:
|
59
56
|
- - ~>
|
60
57
|
- !ruby/object:Gem::Version
|
61
58
|
version: 2.6.3
|
59
|
+
none: false
|
60
|
+
prerelease: false
|
61
|
+
type: :runtime
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: hitimes
|
64
|
-
|
65
|
-
none: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
65
|
requirements:
|
67
66
|
- - ~>
|
68
67
|
- !ruby/object:Gem::Version
|
69
68
|
version: 1.1.1
|
70
|
-
type: :runtime
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
69
|
none: false
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
74
71
|
requirements:
|
75
72
|
- - ~>
|
76
73
|
- !ruby/object:Gem::Version
|
77
74
|
version: 1.1.1
|
78
|
-
|
75
|
+
none: false
|
76
|
+
prerelease: false
|
77
|
+
type: :runtime
|
78
|
+
description:
|
79
79
|
email: eregontp@gmail.com
|
80
80
|
executables:
|
81
81
|
- perfer
|
82
82
|
extensions: []
|
83
83
|
extra_rdoc_files: []
|
84
84
|
files:
|
85
|
-
-
|
86
|
-
|
87
|
-
-
|
88
|
-
|
89
|
-
-
|
90
|
-
|
91
|
-
-
|
92
|
-
|
93
|
-
-
|
94
|
-
|
95
|
-
-
|
96
|
-
|
97
|
-
-
|
98
|
-
|
99
|
-
-
|
100
|
-
|
101
|
-
-
|
102
|
-
|
103
|
-
-
|
104
|
-
|
85
|
+
- !binary |-
|
86
|
+
YmluL3BlcmZlcg==
|
87
|
+
- !binary |-
|
88
|
+
bGliL3BlcmZlci5yYg==
|
89
|
+
- !binary |-
|
90
|
+
bGliL3BlcmZlci9jbGkucmI=
|
91
|
+
- !binary |-
|
92
|
+
bGliL3BlcmZlci9jb25maWd1cmF0aW9uLnJi
|
93
|
+
- !binary |-
|
94
|
+
bGliL3BlcmZlci9lcnJvcnMucmI=
|
95
|
+
- !binary |-
|
96
|
+
bGliL3BlcmZlci9mb3JtYXR0ZXIucmI=
|
97
|
+
- !binary |-
|
98
|
+
bGliL3BlcmZlci9naXQucmI=
|
99
|
+
- !binary |-
|
100
|
+
bGliL3BlcmZlci9qb2IucmI=
|
101
|
+
- !binary |-
|
102
|
+
bGliL3BlcmZlci9wbGF0Zm9ybS5yYg==
|
103
|
+
- !binary |-
|
104
|
+
bGliL3BlcmZlci9yZXN1bHQucmI=
|
105
|
+
- !binary |-
|
106
|
+
bGliL3BlcmZlci9zZXNzaW9uLnJi
|
107
|
+
- !binary |-
|
108
|
+
bGliL3BlcmZlci9zdGF0aXN0aWNzLnJi
|
109
|
+
- !binary |-
|
110
|
+
bGliL3BlcmZlci9zdG9yZS5yYg==
|
111
|
+
- !binary |-
|
112
|
+
bGliL3BlcmZlci9mb3JtYXR0ZXIvbWVhc3VyZW1lbnRzX2Zvcm1hdHRlci5y
|
113
|
+
Yg==
|
114
|
+
- !binary |-
|
115
|
+
bGliL3BlcmZlci9mb3JtYXR0ZXIvcmVzdWx0c19mb3JtYXR0ZXIucmI=
|
116
|
+
- !binary |-
|
117
|
+
bGliL3BlcmZlci9mb3JtYXR0ZXIvc2Vzc2lvbl9mb3JtYXR0ZXIucmI=
|
118
|
+
- !binary |-
|
119
|
+
bGliL3BlcmZlci9ncmFwaGVyL3JfZ3JhcGhlci5yYg==
|
120
|
+
- !binary |-
|
121
|
+
bGliL3BlcmZlci9qb2IvaW5wdXRfc2l6ZV9qb2IucmI=
|
122
|
+
- !binary |-
|
123
|
+
bGliL3BlcmZlci9qb2IvaXRlcmF0aW9uX2pvYi5yYg==
|
124
|
+
- !binary |-
|
125
|
+
bGliL3BlcmZlci9wbGF0Zm9ybS9wb3NpeC5yYg==
|
126
|
+
- !binary |-
|
127
|
+
bGliL3BlcmZlci9wbGF0Zm9ybS93aW5kb3dzLnJi
|
105
128
|
- README.md
|
106
129
|
- LICENSE
|
107
130
|
- perfer.gemspec
|
108
131
|
homepage: https://github.com/jruby/perfer
|
109
132
|
licenses: []
|
110
|
-
post_install_message:
|
133
|
+
post_install_message:
|
111
134
|
rdoc_options: []
|
112
135
|
require_paths:
|
113
136
|
- lib
|
114
137
|
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
-
none: false
|
116
138
|
requirements:
|
117
139
|
- - ! '>='
|
118
140
|
- !ruby/object:Gem::Version
|
119
|
-
version:
|
120
|
-
|
141
|
+
version: !binary |-
|
142
|
+
MA==
|
121
143
|
none: false
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
145
|
requirements:
|
123
146
|
- - ! '>='
|
124
147
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
148
|
+
version: !binary |-
|
149
|
+
MA==
|
150
|
+
none: false
|
126
151
|
requirements: []
|
127
|
-
rubyforge_project:
|
128
|
-
rubygems_version: 1.8.
|
129
|
-
signing_key:
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 1.8.24
|
154
|
+
signing_key:
|
130
155
|
specification_version: 3
|
131
156
|
summary: A benchmark tool for all rubies!
|
132
157
|
test_files: []
|
133
|
-
has_rdoc:
|