benchmark-extensions 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +93 -0
- data/Rakefile +1 -0
- data/benchmark-extensions.gemspec +20 -0
- data/bin/benchmark +67 -0
- data/examples/plugins/Gemfile +3 -0
- data/examples/plugins/init.rb +20 -0
- data/examples/plugins/simulations/manuscript.rb +20 -0
- data/examples/report_aggregator.rb +39 -0
- data/lib/benchmark-extensions.rb +8 -0
- data/lib/bme/report_aggregator.rb +44 -0
- data/lib/bme/runner.rb +17 -0
- data/lib/bme/simulations.rb +81 -0
- data/lib/bme/version.rb +3 -0
- metadata +84 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Lenny Marks
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
Ruby benchmark extensions
|
2
|
+
==============================
|
3
|
+
|
4
|
+
* ```BME::Runner.run(threads, repetitions, &blk)``` - Run block of code in :threads threads, :repetition times each thread.
|
5
|
+
<pre>
|
6
|
+
BME::Runner.run(2, 2) do |run_id|
|
7
|
+
puts run_id
|
8
|
+
end
|
9
|
+
|
10
|
+
[0][0]
|
11
|
+
[0][1]
|
12
|
+
[1][0]
|
13
|
+
[1][1]
|
14
|
+
</pre>
|
15
|
+
* ```BME::ReportAggregator``` - Threadsafe aggregating wrapper around ```#report``` from SDK Benchmark.
|
16
|
+
See: [examples/report_aggregator.rb](examples/report_aggregator.rb)
|
17
|
+
* ```benchmark``` executable - A mini-framework with automatic discovery and statistic reporting for pluggable ```simulations```.
|
18
|
+
<pre>
|
19
|
+
$ bundle exec benchmark --help
|
20
|
+
Usage: benchmark [options]
|
21
|
+
-h, --help Display this screen
|
22
|
+
-t, --threads NUM Number of simultaneous threads per thread group
|
23
|
+
-r, --repetitions NUM Number of repetitions per thread
|
24
|
+
-s, --simulation NAME Run only specified simulation
|
25
|
+
|
26
|
+
$ bundle exec benchmark -s ManView -t 3 -r 2
|
27
|
+
user system total real
|
28
|
+
[1][0] ManView GA1001 0.088000 0.000000 0.088000 ( 0.086000)
|
29
|
+
[1][0] ManView GA1001 0.020000 0.000000 0.020000 ( 0.020000)
|
30
|
+
.....
|
31
|
+
ManView.history 0.224000 0.000000 0.224000 ( 0.222000)
|
32
|
+
ManView.tracking_info 0.091000 0.000000 0.091000 ( 0.091000)
|
33
|
+
ManView.related_manuscripts 0.209000 0.000000 0.209000 ( 0.209000)
|
34
|
+
ManView.contact_info 0.322000 0.000000 0.322000 ( 0.322000)
|
35
|
+
.....
|
36
|
+
ManView 3.251001 0.000000 3.251001 ( 3.252001)
|
37
|
+
>total: 3.251001 0.000000 3.251001 ( 3.252001)
|
38
|
+
|
39
|
+
ManView.history(12) total(0.22200) avg(0.01850) median(0.00950) std(0.02259) min(0.00500) max(0.08600)
|
40
|
+
ManView.tracking_info(12) total(0.09100) avg(0.00758) median(0.00450) std(0.00682) min(0.00200) max(0.02000)
|
41
|
+
ManView.related_manuscripts(12) total(0.20900) avg(0.01742) median(0.01100) std(0.01274) min(0.00800) max(0.04800)
|
42
|
+
ManView.contact_info(12) total(0.32200) avg(0.02683) median(0.01650) std(0.02814) min(0.00700) max(0.09900)
|
43
|
+
.....
|
44
|
+
ManView(216) total(3.25200) avg(0.01506) median(0.00500) std(0.03255) min(0.00000) max(0.32000)
|
45
|
+
</pre>
|
46
|
+
|
47
|
+
## Plugins
|
48
|
+
|
49
|
+
Ruby files in the ```simulations/``` directory are automatically loaded.
|
50
|
+
|
51
|
+
A class is plugged in to the framework via the ```simulation``` method. ```simulation``` expects a block that returns a list of elements
|
52
|
+
used to instantiate simulation instances.
|
53
|
+
An instance of the simulation class will be instantiated for each batch item and all ```simulate_*'```
|
54
|
+
methods will be executed and benchmarked. The batch item a simulation instance was instantiated
|
55
|
+
with is accessible as ```#subject```.
|
56
|
+
|
57
|
+
e.g.
|
58
|
+
|
59
|
+
class ManView
|
60
|
+
simulation 'ManView' do
|
61
|
+
%w(GA1001 AA1002)
|
62
|
+
end
|
63
|
+
|
64
|
+
def simulate_events
|
65
|
+
....
|
66
|
+
|
67
|
+
def simulate_contact_info
|
68
|
+
...
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def manuscript
|
73
|
+
@manuscript ||= Manuscript.find(subject)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
### Customizing
|
78
|
+
|
79
|
+
The benchmark script loads ```init.rb``` which is where your customizations should go.
|
80
|
+
|
81
|
+
To override simulation methods (i.e. to decorate) you can use ```Simulation.add_helper(SimulationHelpers)```
|
82
|
+
to specify a mixin to be added to all simulation classes.
|
83
|
+
|
84
|
+
e.g. # init.rb
|
85
|
+
|
86
|
+
module SimulationHelpers
|
87
|
+
def run
|
88
|
+
EOPCommon::DoInSession.execute_new { super }
|
89
|
+
end
|
90
|
+
....
|
91
|
+
end
|
92
|
+
|
93
|
+
Simulation.add_helper(SimulationHelpers)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bme/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = 'benchmark-extensions'
|
8
|
+
gem.version = BME::VERSION
|
9
|
+
gem.authors = ['Lenny Marks']
|
10
|
+
gem.email = %w(lenny@aps.org)
|
11
|
+
gem.description = %q{Benchmark extensions}
|
12
|
+
gem.summary = %q{Benchmark extensions}
|
13
|
+
gem.homepage = ''
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = %w(benchmark)
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = %w(lib)
|
19
|
+
gem.add_dependency('easystats')
|
20
|
+
end
|
data/bin/benchmark
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
root_dir = File.dirname(ENV['BUNDLE_GEMFILE'])
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require 'benchmark'
|
7
|
+
|
8
|
+
options = {}
|
9
|
+
optparse = OptionParser.new do |opts|
|
10
|
+
opts.banner = 'Usage: benchmark [options]'
|
11
|
+
|
12
|
+
opts.on('-h', '--help', 'Display this screen') do
|
13
|
+
puts opts
|
14
|
+
exit(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on('-t', '--threads NUM', 'Number of simultaneous threads per thread group') do |v|
|
18
|
+
options[:threads] = v.to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on('-r', '--repetitions NUM', 'Number of repetitions per thread') do |v|
|
22
|
+
options[:repetitions] = v.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on('-s', '--simulation NAME', 'Run only specified simulation') do |v|
|
26
|
+
options[:simulation] = v
|
27
|
+
end
|
28
|
+
end
|
29
|
+
optparse.parse!
|
30
|
+
|
31
|
+
options[:threads] ||= 1
|
32
|
+
options[:repetitions] ||= 1
|
33
|
+
|
34
|
+
require 'benchmark-extensions'
|
35
|
+
require 'bme/simulations'
|
36
|
+
|
37
|
+
init_file = "#{root_dir}/init.rb"
|
38
|
+
require init_file if init_file
|
39
|
+
|
40
|
+
Dir.glob("#{root_dir}/simulations/*.rb").each { |f| require f }
|
41
|
+
|
42
|
+
simulations = BME::Simulation.select { |c| options[:simulation] ? c.name == options[:simulation] : true }
|
43
|
+
|
44
|
+
labels = simulations.reduce([]) do |l, simulation_class|
|
45
|
+
simulation_class.steps.each do |s|
|
46
|
+
l << "#{simulation_class.label}.#{s}"
|
47
|
+
end
|
48
|
+
l << simulation_class.label
|
49
|
+
l
|
50
|
+
end
|
51
|
+
|
52
|
+
aggregator = nil
|
53
|
+
|
54
|
+
Benchmark.bm(40, *labels, '>total:') do |bm|
|
55
|
+
aggregator = BME::ReportAggregator.new(bm)
|
56
|
+
|
57
|
+
BME::Runner.run(options[:threads], options[:repetitions]) do |run_id|
|
58
|
+
simulations.each do |simulation_class|
|
59
|
+
next if options[:simulation] && simulation_class.name != options[:simulation]
|
60
|
+
simulation_class.run(run_id, aggregator)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
aggregator.totals(labels)
|
65
|
+
end
|
66
|
+
|
67
|
+
puts "\n#{aggregator.stats(40, 5, labels)}"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Fake transaction like class for demonstration purposese
|
2
|
+
class Transaction
|
3
|
+
class << self
|
4
|
+
def exec(&blk)
|
5
|
+
blk.call
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module SimulationHelpers
|
11
|
+
def run
|
12
|
+
Transaction.exec { super }
|
13
|
+
end
|
14
|
+
|
15
|
+
def some_helper
|
16
|
+
'foo'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
BME::Simulation.add_helper(SimulationHelpers)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Manuscript
|
2
|
+
simulation 'Manuscript' do
|
3
|
+
%w(GA1001 GA1002)
|
4
|
+
end
|
5
|
+
|
6
|
+
def simulate_items
|
7
|
+
some_helper # see SimulationHelpers in init.rb
|
8
|
+
manuscript.items
|
9
|
+
end
|
10
|
+
|
11
|
+
def simulate_history
|
12
|
+
manuscript.history
|
13
|
+
sleep(0.1)
|
14
|
+
end
|
15
|
+
|
16
|
+
def manuscript
|
17
|
+
# more typical would be Manuscript.find(subject)
|
18
|
+
@manuscript ||= Struct.new(:order_id, :items, :history).new(:items => [], :history => [])
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
|
4
|
+
|
5
|
+
require 'bundler'
|
6
|
+
Bundler.setup
|
7
|
+
|
8
|
+
require 'benchmark'
|
9
|
+
require 'benchmark-extensions'
|
10
|
+
|
11
|
+
labels = %w(groupa.foo groupa.bar groupa.baz groupa)
|
12
|
+
labels.concat %w(groupb.foo groupb.bar groupb.baz groupb)
|
13
|
+
labels.concat %w(foo bar baz)
|
14
|
+
|
15
|
+
aggregator = nil
|
16
|
+
|
17
|
+
Benchmark.bm(40, *labels, '>total:') do |bm|
|
18
|
+
aggregator = BME::ReportAggregator.new(bm)
|
19
|
+
|
20
|
+
# to threads 2 repetitions each
|
21
|
+
BME::Runner.run(2, 2) do |run_id|
|
22
|
+
3.times do |i|
|
23
|
+
aggregator.report("#{run_id} #{i} groupa.foo", 'groupa.foo', 'groupa', 'foo') { sleep(0.1) }
|
24
|
+
aggregator.report("#{run_id} #{i} groupa.bar", 'groupa.bar', 'groupa', 'bar') { sleep(0.1) }
|
25
|
+
aggregator.report("#{run_id} #{i} groupa.baz", 'groupa.baz', 'groupa', 'baz') { sleep(0.1) }
|
26
|
+
end
|
27
|
+
|
28
|
+
3.times do |i|
|
29
|
+
aggregator.report("#{run_id} #{i} grouba.foo", 'groupb.foo', 'groupb', 'foo') { sleep(0.1) }
|
30
|
+
aggregator.report("#{run_id} #{i} groupb.bar", 'groupb.bar', 'groupb', 'baz') { sleep(0.1) }
|
31
|
+
aggregator.report("#{run_id} #{i} groupb.baz", 'groupb.baz', 'groupb', 'baz') { sleep(0.1) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
aggregator.totals(labels)
|
36
|
+
end
|
37
|
+
|
38
|
+
puts "\n#{aggregator.stats(40, 5, labels)}"
|
39
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'easystats'
|
2
|
+
|
3
|
+
module BME
|
4
|
+
class ReportAggregator
|
5
|
+
attr_reader :keyed_reports, :benchmark, :reports
|
6
|
+
|
7
|
+
def initialize(benchmark)
|
8
|
+
@benchmark = benchmark
|
9
|
+
@keyed_reports = {}
|
10
|
+
@reports = []
|
11
|
+
@mutex = Mutex.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def report(label, *keys, &blk)
|
15
|
+
@mutex.synchronize do
|
16
|
+
reports << r = benchmark.report(label, &blk)
|
17
|
+
keys.each do |k|
|
18
|
+
(keyed_reports[k] ||= []) << r
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def totals(labels)
|
24
|
+
totals = labels.reduce([]) { |l, label| l << tally(keyed_reports.fetch(label)); l }
|
25
|
+
totals << tally(reports)
|
26
|
+
totals
|
27
|
+
end
|
28
|
+
|
29
|
+
def tally(l)
|
30
|
+
l.reduce { |r, total| total += r }
|
31
|
+
end
|
32
|
+
|
33
|
+
def stats(width, precision, labels)
|
34
|
+
buf = ''
|
35
|
+
p = precision
|
36
|
+
labels.each do |k|
|
37
|
+
realtimes = keyed_reports.fetch(k).map(&:real)
|
38
|
+
buf << sprintf("%-#{width}s total(%.#{p}f) avg(%.#{p}f) median(%.#{p}f) std(%.#{p}f) min(%.#{p}f) max(%.#{p}f) \n",
|
39
|
+
"#{k}(#{realtimes.size})", realtimes.sum, realtimes.average, realtimes.median, realtimes.standard_deviation, realtimes.min, realtimes.max)
|
40
|
+
end
|
41
|
+
buf
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/bme/runner.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module BME
|
2
|
+
class Runner
|
3
|
+
class << self
|
4
|
+
def run(threads, repetitions, &blk)
|
5
|
+
thread_group = []
|
6
|
+
threads.times do |thread_index|
|
7
|
+
thread_group << Thread.new do
|
8
|
+
repetitions.times do |i|
|
9
|
+
blk.call("[#{thread_index}][#{i}]")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
thread_group.map(&:join)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module BME
|
2
|
+
class Simulation
|
3
|
+
extend Enumerable
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_reader :simulations, :helpers
|
7
|
+
|
8
|
+
def add(simulation_class)
|
9
|
+
simulations << simulation_class
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(&blk)
|
13
|
+
simulations.each(&blk)
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_helper(mixin)
|
17
|
+
self.helpers << mixin
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@simulations = []
|
22
|
+
@helpers = []
|
23
|
+
end
|
24
|
+
|
25
|
+
module SimulationClassMethods
|
26
|
+
def steps
|
27
|
+
instance_methods.map { |m| m[/^simulate_(.*)/, 1] }.compact
|
28
|
+
end
|
29
|
+
|
30
|
+
def run(run_id, aggregator)
|
31
|
+
batch.each do |*args|
|
32
|
+
s = new
|
33
|
+
s.send(:setup, run_id, aggregator, *args)
|
34
|
+
s.send(:run)
|
35
|
+
s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module SimulationInstanceMethods
|
41
|
+
attr_reader :run_id, :aggregator, :batch_args
|
42
|
+
|
43
|
+
def subject
|
44
|
+
batch_args.first
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def qualified_label
|
50
|
+
"#{run_id} #{self.class.label} #{subject}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def setup(run_id, aggregator, *args)
|
54
|
+
@run_id, @aggregator, @batch_args = run_id, aggregator, args
|
55
|
+
end
|
56
|
+
|
57
|
+
def run
|
58
|
+
self.class.steps.each do |step|
|
59
|
+
aggregator.report(qualified_label, self.class.label, "#{self.class.label}.#{step}" ) { send("simulate_#{step}") }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module SimulationExtension
|
65
|
+
def simulation(label = name, &blk)
|
66
|
+
Simulation.add(self)
|
67
|
+
|
68
|
+
define_singleton_method(:batch, &blk)
|
69
|
+
define_singleton_method(:label) { label }
|
70
|
+
|
71
|
+
extend SimulationClassMethods
|
72
|
+
include SimulationInstanceMethods
|
73
|
+
|
74
|
+
Simulation.helpers.each do |h|
|
75
|
+
include h
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
Class.send(:include, SimulationExtension)
|
81
|
+
end
|
data/lib/bme/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: benchmark-extensions
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Lenny Marks
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: easystats
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Benchmark extensions
|
31
|
+
email:
|
32
|
+
- lenny@aps.org
|
33
|
+
executables:
|
34
|
+
- benchmark
|
35
|
+
extensions: []
|
36
|
+
extra_rdoc_files: []
|
37
|
+
files:
|
38
|
+
- .gitignore
|
39
|
+
- Gemfile
|
40
|
+
- LICENSE.txt
|
41
|
+
- README.md
|
42
|
+
- Rakefile
|
43
|
+
- benchmark-extensions.gemspec
|
44
|
+
- bin/benchmark
|
45
|
+
- examples/plugins/Gemfile
|
46
|
+
- examples/plugins/init.rb
|
47
|
+
- examples/plugins/simulations/manuscript.rb
|
48
|
+
- examples/report_aggregator.rb
|
49
|
+
- lib/benchmark-extensions.rb
|
50
|
+
- lib/bme/report_aggregator.rb
|
51
|
+
- lib/bme/runner.rb
|
52
|
+
- lib/bme/simulations.rb
|
53
|
+
- lib/bme/version.rb
|
54
|
+
homepage: ''
|
55
|
+
licenses: []
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
hash: -4387911391081834859
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ! '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
hash: -4387911391081834859
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.8.24
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: Benchmark extensions
|
84
|
+
test_files: []
|