benchmark-bigo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 423aefb007643b70b3a3b6948ec4be73a699e39e
4
+ data.tar.gz: 58fb68d5bc09db75769948213ba3d7f493cdc433
5
+ SHA512:
6
+ metadata.gz: 5725e3a65ab19f74b6ebcb12a949247abf1d66cd22ebe8394da76e876ce1014a3628c1398e39daaab81597137f67976c88dcc564e07c4994c747bb47aaea311b
7
+ data.tar.gz: 674a6df9fa33fc2963906343d0f11dad96e4ab12345186743f6d5a3d0c3df40e82b9d318342e76917a2cdac3c7e1628add50bf296423cb1d6056c6346c5cecc3
data/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 0.0.1 / 2014-05-12
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,8 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/benchmark/bigo.rb
6
+ lib/benchmark/bigo/report.rb
7
+ lib/benchmark/bigo/job.rb
8
+ lib/benchmark/bigo/chart.erb
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ [![Build Status](https://secure.travis-ci.org/davy/benchmark-bigo.png)](http://travis-ci.org/davy/benchmark-bigo)
2
+
3
+ # benchmark-bigo
4
+
5
+ * http://github.com/davy/benchmark-bigo
6
+
7
+ ## DESCRIPTION:
8
+
9
+ Benchmark objects to help calculate Big O behavior
10
+
11
+ ## SYNOPSIS:
12
+
13
+ ```ruby
14
+ require 'benchmark/bigo'
15
+
16
+ report = Benchmark.bigo do |x|
17
+
18
+
19
+ # increments is the total number of data points to collect
20
+ x.increments = 6
21
+
22
+ # generator should construct a test object of the given size
23
+ # example of an Array generator
24
+ x.generator {|size| (0...size).to_a.shuffle }
25
+
26
+ # specifies how the size of the object should grow
27
+ # options: linear, logarithmic
28
+ #
29
+ # specifies that arrays should grow linearly by 1000
30
+ x.linear 1000
31
+
32
+ # report takes a label and a block.
33
+ # block is passed in the generated object and the size of that object
34
+ x.report("#at") {|generated, size| generated.at rand(size) }
35
+ x.report("#index") {|generated, size| generated.index rand(size) }
36
+ x.report("#empty-index") {|generated, size| generated.index 'foo' }
37
+
38
+ # save results in JSON format
39
+ x.data! 'chart_array_simple.json'
40
+
41
+ # generate HTML chart using ChartKick
42
+ x.chart! 'chart_array_simple.html'
43
+
44
+ # for each report, create a comparison chart showing the report
45
+ # and scaled series for O(log n), O(n), O(n log n), and O(n squared)
46
+ x.compare!
47
+
48
+ end
49
+ ```
50
+
51
+ ## REQUIREMENTS:
52
+
53
+ * benchmark-ips (http://github.com/evanphx/benchmark-ips)
54
+
55
+ ## INSTALL:
56
+
57
+ $ gem install benchmark-bigo
58
+
59
+ ## DEVELOPERS:
60
+
61
+ After checking out the source, run:
62
+
63
+ $ rake newb
64
+
65
+ This task will install any missing dependencies, run the tests/specs,
66
+ and generate the RDoc.
67
+
68
+ ## LICENSE:
69
+
70
+ (The MIT License)
71
+
72
+ Copyright (c) 2014 Davy Stevenson
73
+
74
+ Permission is hereby granted, free of charge, to any person obtaining
75
+ a copy of this software and associated documentation files (the
76
+ 'Software'), to deal in the Software without restriction, including
77
+ without limitation the rights to use, copy, modify, merge, publish,
78
+ distribute, sublicense, and/or sell copies of the Software, and to
79
+ permit persons to whom the Software is furnished to do so, subject to
80
+ the following conditions:
81
+
82
+ The above copyright notice and this permission notice shall be
83
+ included in all copies or substantial portions of the Software.
84
+
85
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
88
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
89
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
90
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
91
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ # -*- ruby -*-
2
+
3
+ require "rubygems"
4
+ require "hoe"
5
+
6
+ Hoe.plugin :minitest
7
+
8
+ Hoe.spec "benchmark-bigo" do
9
+
10
+ developer("Davy Stevenson", "davy.stevenson@gmail.com")
11
+
12
+ extra_deps << ["benchmark-ips", '~> 2.0']
13
+ extra_deps << ["chartkick", '~> 1.2', '>= 1.2.4']
14
+
15
+ self.readme_file = 'README.md'
16
+
17
+ license "MIT" # this should match the license in the README
18
+ end
19
+
20
+ # vim: syntax=ruby
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ require 'erb'
3
+ require 'chartkick'
4
+ require 'benchmark/ips'
5
+ require 'benchmark/bigo/report'
6
+ require 'benchmark/bigo/job'
7
+
8
+ module Benchmark
9
+
10
+ module BigO
11
+ VERSION = "0.0.1"
12
+
13
+ def bigo
14
+ suite = nil
15
+
16
+ sync, $stdout.sync = $stdout.sync, true
17
+
18
+ if defined? Benchmark::Suite and Suite.current
19
+ suite = Benchmark::Suite.current
20
+ end
21
+
22
+ quiet = suite && !suite.quiet?
23
+
24
+ job = Job.new({:suite => suite,
25
+ :quiet => quiet
26
+ })
27
+
28
+ yield job
29
+
30
+ $stdout.puts "Calculating -------------------------------------" unless quiet
31
+
32
+ job.run_warmup
33
+
34
+ $stdout.puts "-------------------------------------------------" unless quiet
35
+
36
+ job.run
37
+
38
+ if job.data?
39
+ job.generate_data
40
+ end
41
+
42
+ if job.chart?
43
+ job.generate_chart
44
+ end
45
+
46
+ $stdout.sync = sync
47
+
48
+ return job.full_report
49
+ end
50
+ end
51
+
52
+ extend Benchmark::BigO
53
+ end
@@ -0,0 +1,17 @@
1
+ <html>
2
+ <head>
3
+ <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
4
+ <script src="http://www.google.com/jsapi"></script>
5
+ <script src="http://code.highcharts.com/highcharts.js"></script>
6
+ <script src="http://chartkick.com/chartkick.js"></script>
7
+ </head>
8
+ <body>
9
+
10
+ <% for chart in charts %>
11
+ <h1><%= chart[:name] %></h1>
12
+
13
+ <%= line_chart chart[:data], chart[:opts] %>
14
+ <% end %>
15
+ </body>
16
+ </html>
17
+
@@ -0,0 +1,204 @@
1
+ module Benchmark
2
+
3
+ module BigO
4
+ class Job < IPS::Job
5
+
6
+ class Entry < IPS::Job::Entry
7
+
8
+ def initialize label, action, generated, size
9
+ super label, action
10
+
11
+ if @as_action
12
+ raise "as_action not supported yet"
13
+ else
14
+ raise ArgumentError if action.arity != 2
15
+ @call_loop = false
16
+ end
17
+
18
+ # these objects can be very large, do not want
19
+ # them to be displayed as part of inspect
20
+ define_singleton_method(:generated) { generated }
21
+ define_singleton_method(:size) { size }
22
+ end
23
+
24
+ def call_times(times)
25
+ act = @action
26
+
27
+ i = 0
28
+ while i < times
29
+ act.call generated, size
30
+ i += 1
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ include Chartkick::Helper
37
+
38
+ # how many total increments are being measured
39
+ attr_accessor :increments
40
+
41
+ # whether to graph the results on a log scale
42
+ attr_accessor :logscale
43
+
44
+ # whether to generate a chart of the results
45
+ # if nil, do not generate chart
46
+ # else string is name of file to write chart out to
47
+ attr_reader :chart
48
+
49
+ def initialize opts={}
50
+ super
51
+
52
+ @full_report = Report.new
53
+ @generator = nil
54
+
55
+ # defaults
56
+ linear
57
+ @increments = 5
58
+ @logscale = false
59
+ @chart = nil
60
+ @data_file = nil
61
+ end
62
+
63
+ def config opts
64
+ super
65
+ @increments = opts[:increments] if opts[:increments]
66
+ @logscale = opts[:logscale] if opts[:logscale]
67
+ @full_report.logscale! if @logscale
68
+ end
69
+
70
+ def chart?
71
+ @chart
72
+ end
73
+
74
+ def chart! filename='chart.html'
75
+ @chart = filename
76
+ end
77
+
78
+ def data?
79
+ @data_file
80
+ end
81
+
82
+ def data! filename='data.json'
83
+ @data_file = filename
84
+ end
85
+
86
+ def logscale= val
87
+ @logscale = val
88
+ @full_report.logscale! if @logscale
89
+ end
90
+
91
+ def generator &blk
92
+ @generator = blk
93
+
94
+ raise ArgumentError, "no block" unless @generator
95
+ end
96
+
97
+
98
+ # use a generator that creates a randomized object
99
+ # represented by the symbol passed to the method
100
+ def generate sym
101
+
102
+ case sym
103
+
104
+ # generates an Array containing shuffled integer values from 0 to size
105
+ when :array
106
+ @generator = Proc.new{|size| (0...size).to_a.shuffle }
107
+
108
+ # when :string
109
+ # to do
110
+
111
+ else
112
+ raise "#{sym} is not a supported object type"
113
+ end
114
+ end
115
+
116
+ # custom incrementer
117
+ def incrementer &blk
118
+ @incrementer = blk
119
+ raise ArgumentError, "no block" unless @incrementer
120
+ end
121
+
122
+ # linear incrementer
123
+ def linear increments=100
124
+ @incrementer = Proc.new {|i| i * increments }
125
+ @logscale = false
126
+ end
127
+
128
+ # logarithmic incrementer
129
+ def logarithmic base=10
130
+ @incrementer = Proc.new {|i| base ** (i-1) }
131
+ @full_report.logscale!
132
+ @logscale = true
133
+ end
134
+
135
+ def sizes
136
+ (1..@increments).collect do |idx|
137
+ @incrementer.call(idx).to_i
138
+ end
139
+ end
140
+
141
+ def item label="", str=nil, &blk # :yield:
142
+ if blk and str
143
+ raise ArgumentError, "specify a block and a str, but not both"
144
+ end
145
+
146
+ action = str || blk
147
+ raise ArgumentError, "no block or string" unless action
148
+
149
+ for size in sizes
150
+ generated = @generator.call(size)
151
+
152
+ label_size = "#{label} #{size}"
153
+ @list.push Entry.new(label_size, action, generated, size)
154
+ end
155
+
156
+ self
157
+ end
158
+ alias_method :report, :item
159
+
160
+ def run_warmup
161
+ super
162
+
163
+ max_timing = @timing.values.max
164
+ @full_report.per_iterations = 10**Math.log10(max_timing).ceil
165
+ end
166
+
167
+ def generate_data
168
+ return if @data_file.nil?
169
+
170
+ all_data = @full_report.chart_data
171
+
172
+ File.open @data_file, 'w' do |f|
173
+ f.write JSON.pretty_generate(all_data)
174
+ end
175
+ end
176
+
177
+ def generate_chart
178
+ return if @chart.nil?
179
+
180
+ all_data = @full_report.chart_data
181
+
182
+ charts = []
183
+ charts << { name: 'Growth Chart', data: all_data, opts: @full_report.chart_opts(all_data) }
184
+
185
+ if compare?
186
+ all_sizes = sizes
187
+ for chart_data in all_data
188
+ comparison_data = @full_report.comparison_chart_data chart_data, all_sizes
189
+ charts << { name: chart_data[:name], data: comparison_data, opts: @full_report.chart_opts(chart_data) }
190
+ end
191
+ end
192
+
193
+ template_file = File.join File.dirname(__FILE__), 'chart.erb'
194
+ template = ERB.new(File.read(template_file))
195
+
196
+ File.open @chart, 'w' do |f|
197
+ f.write template.result(binding)
198
+ end
199
+
200
+ end
201
+
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,130 @@
1
+ module Benchmark
2
+
3
+ module BigO
4
+ class Report
5
+
6
+ attr_accessor :per_iterations
7
+ attr_reader :entries
8
+
9
+ def initialize
10
+ @per_iterations = 0
11
+ @entries = {}
12
+ @logscale = false
13
+ end
14
+
15
+ def logscale?
16
+ @logscale
17
+ end
18
+
19
+ def logscale!
20
+ @logscale = true
21
+ end
22
+
23
+ def add_entry label, microseconds, iters, ips, ips_sd, measurement_cycle
24
+ group_label = label.split(' ').first
25
+
26
+ @entries[group_label] ||= []
27
+ @entries[group_label] << Benchmark::IPS::Report::Entry.new(label, microseconds, iters, ips, ips_sd, measurement_cycle)
28
+ @entries[group_label].last
29
+ end
30
+
31
+ def scaled_iterations
32
+ (@per_iterations.to_f * 50 )
33
+ end
34
+
35
+ def chart_hash group_label
36
+ @entries[group_label].collect do |report|
37
+ size = report.label.split(' ').last.to_i
38
+ seconds_per_scaled_iters = scaled_iterations / report.ips.to_f
39
+
40
+ {label: size,
41
+ seconds_per_scaled_iters: seconds_per_scaled_iters,
42
+ ips: report.ips
43
+ }
44
+ end
45
+ end
46
+
47
+ def chart_for group_label
48
+ chart_hash = chart_hash group_label
49
+ Hash[chart_hash.collect{|h| [h[:label], h[:seconds_per_scaled_iters]]}]
50
+ end
51
+
52
+ def chart_data
53
+ @entries.keys.map do |k|
54
+ data = chart_for k
55
+ {name: k, data: data }
56
+ end
57
+ end
58
+
59
+ def chart_opts chart_data
60
+
61
+ axis_type = logscale? ? 'logarithmic' : 'linear'
62
+
63
+ if chart_data.is_a? Array
64
+ min = chart_data.collect{|d| d[:data].values.min}.min
65
+ max = chart_data.collect{|d| d[:data].values.max}.max
66
+
67
+ elsif chart_data.is_a? Hash
68
+ min = chart_data[:data].values.min
69
+ max = chart_data[:data].values.max
70
+ end
71
+
72
+ orange = "#f0662d"
73
+ purple = "#8062a6"
74
+ light_green = "#7bc545"
75
+ med_blue = "#0883b2"
76
+ yellow = "#ffaa00"
77
+
78
+ {
79
+ discrete: true,
80
+ width: "800px",
81
+ height: "500px",
82
+ min: (min * 0.8).floor,
83
+ max: (max * 1.2).ceil,
84
+ library: {
85
+ colors: [orange, purple, light_green, med_blue, yellow],
86
+ xAxis: {type: axis_type, title: {text: "Size"}},
87
+ yAxis: {type: axis_type, title: {text: "Seconds per #{scaled_iterations.to_i} Iterations"}}
88
+ }
89
+ }
90
+ end
91
+
92
+ def comparison_chart_data chart_data, sizes
93
+ sample_size = sizes.first
94
+
95
+ # can't take log of 1,
96
+ # so it can't be used as the sample
97
+ if sample_size == 1
98
+ sample_size = sizes[1]
99
+ end
100
+
101
+ sample = chart_data[:data][sample_size]
102
+
103
+ logn_sample = sample/Math.log10(sample_size)
104
+ n_sample = sample/sample_size
105
+ nlogn_sample = sample/(sample_size * Math.log10(sample_size))
106
+ n2_sample = sample/(sample_size * sample_size)
107
+
108
+ logn_data = {}
109
+ n_data = {}
110
+ nlogn_data = {}
111
+ n2_data = {}
112
+
113
+ sizes.each do |n|
114
+ logn_data[n] = Math.log10(n) * logn_sample
115
+ n_data[n] = n * n_sample
116
+ nlogn_data[n] = n * Math.log10(n) * nlogn_sample
117
+ n2_data[n] = n * n * n2_sample
118
+ end
119
+
120
+ comparison_data = []
121
+ comparison_data << chart_data
122
+ comparison_data << {name: 'log n', data: logn_data}
123
+ comparison_data << {name: 'n', data: n_data}
124
+ comparison_data << {name: 'n log n', data: nlogn_data}
125
+ comparison_data << {name: 'n_sq', data: n2_data}
126
+ comparison_data
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,8 @@
1
+ require "minitest/autorun"
2
+ require "benchmark/bigo"
3
+
4
+ class TestBenchmark::TestBigo < MiniTest::Test
5
+ def test_sanity
6
+ # flunk "write tests or I will kneecap you"
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: benchmark-bigo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Davy Stevenson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-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.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: chartkick
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ - - '>='
35
+ - !ruby/object:Gem::Version
36
+ version: 1.2.4
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: '1.2'
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 1.2.4
47
+ - !ruby/object:Gem::Dependency
48
+ name: minitest
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '5.3'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: '5.3'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rdoc
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: '4.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ version: '4.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: hoe
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ~>
80
+ - !ruby/object:Gem::Version
81
+ version: '3.12'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ version: '3.12'
89
+ description: Benchmark objects to help calculate Big O behavior
90
+ email:
91
+ - davy.stevenson@gmail.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files:
95
+ - History.txt
96
+ - Manifest.txt
97
+ - README.md
98
+ files:
99
+ - History.txt
100
+ - Manifest.txt
101
+ - README.md
102
+ - Rakefile
103
+ - lib/benchmark/bigo.rb
104
+ - lib/benchmark/bigo/report.rb
105
+ - lib/benchmark/bigo/job.rb
106
+ - lib/benchmark/bigo/chart.erb
107
+ - test/benchmark/test_bigo.rb
108
+ - .gemtest
109
+ homepage: http://github.com/davy/benchmark-bigo
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options:
115
+ - --main
116
+ - README.md
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.0.3
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Benchmark objects to help calculate Big O behavior
135
+ test_files:
136
+ - test/benchmark/test_bigo.rb