benchmark-bigo 0.1.0 → 1.0.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.
@@ -9,15 +9,6 @@ module Benchmark
9
9
  def initialize
10
10
  @per_iterations = 0
11
11
  @entries = {}
12
- @logscale = false
13
- end
14
-
15
- def logscale?
16
- @logscale
17
- end
18
-
19
- def logscale!
20
- @logscale = true
21
12
  end
22
13
 
23
14
  def add_entry label, microseconds, iters, ips, ips_sd, measurement_cycle
@@ -28,103 +19,28 @@ module Benchmark
28
19
  @entries[group_label].last
29
20
  end
30
21
 
31
- def scaled_iterations
32
- (@per_iterations.to_f * 50 )
33
- end
34
-
35
- def chart_hash group_label
22
+ # retrieve benchmark data for a particular label
23
+ def data_for group_label
36
24
  @entries[group_label].collect do |report|
37
25
  size = report.label.split(' ').last.to_i
38
- seconds_per_scaled_iters = scaled_iterations / report.ips.to_f
26
+ microseconds_per_iters = 1000000.0 / report.ips.to_f
39
27
 
40
28
  {label: size,
41
- seconds_per_scaled_iters: seconds_per_scaled_iters,
29
+ microseconds_per_iters: microseconds_per_iters,
42
30
  ips: report.ips
43
31
  }
44
32
  end
45
33
  end
46
34
 
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
35
+ # retrieve a summary of data for the benchmark report
36
+ def data
53
37
  @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
38
+ key_data = data_for(k)
39
+ data = Hash[key_data.collect{|h| [h[:label], h[:microseconds_per_iters]]}]
40
+ {name: k, data: data}
70
41
  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
42
  end
91
43
 
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
44
  end
129
45
  end
130
46
  end
@@ -12,6 +12,7 @@
12
12
 
13
13
  <%= line_chart chart[:data], chart[:opts] %>
14
14
  <% end %>
15
+ <h5>Ruby Version: <%= RUBY_VERSION %></h5>
15
16
  </body>
16
17
  </html>
17
18
 
@@ -0,0 +1,70 @@
1
+ require 'tempfile'
2
+
3
+ class Benchmark::BigO::TermPlot
4
+
5
+ def initialize report_data, sizes
6
+ @data = report_data
7
+ @sizes = sizes
8
+ @dat_file = Tempfile.new 'termplot'
9
+ end
10
+
11
+ def generate
12
+
13
+ write_dat_file
14
+
15
+ begin
16
+ IO.popen("gnuplot", "w") { |io| io.puts commands }
17
+ rescue
18
+ puts "You need to have gnuplot installed!"
19
+ puts "brew install gnuplot"
20
+ end
21
+ end
22
+
23
+ def write_dat_file
24
+ File.open(@dat_file.path, 'w') do |file|
25
+ dat_lines.each do |line|
26
+ file.puts line
27
+ end
28
+ end
29
+ end
30
+
31
+ def dat_lines
32
+ lines = []
33
+ @sizes.each do |size|
34
+ line = [size] + @data.collect{|d| d[:data][size] }
35
+ lines << line.join(' ')
36
+ end
37
+ lines
38
+ end
39
+
40
+ def title_for index
41
+ @data[index][:name]
42
+ end
43
+
44
+ def commands
45
+
46
+ cmds = []
47
+ cmds << "set term dumb"
48
+ cmds << "set key top left vertical inside width 3"
49
+
50
+ data_idx = 0
51
+
52
+ while data_idx < @data.length
53
+
54
+ if data_idx == 0
55
+ str = "plot '#{@dat_file.path}'"
56
+ else
57
+ str = "\"\""
58
+ end
59
+
60
+ str += " using 1:#{data_idx+2} title '#{title_for(data_idx)}' with lines"
61
+ str += ",\\" unless data_idx == @data.length-1
62
+
63
+ cmds << str
64
+
65
+ data_idx += 1
66
+ end
67
+
68
+ cmds
69
+ end
70
+ end
@@ -1,8 +1,8 @@
1
1
  module Benchmark
2
2
  module BigO
3
3
  class Version
4
- MAJOR = 0
5
- MINOR = 1
4
+ MAJOR = 1
5
+ MINOR = 0
6
6
  PATCH = 0
7
7
 
8
8
  def self.to_s
@@ -1,5 +1,6 @@
1
1
  require "minitest/autorun"
2
2
  require "benchmark/bigo"
3
+ require "tempfile"
3
4
 
4
5
  class TestBenchmarkBigo < MiniTest::Test
5
6
  def setup
@@ -11,146 +12,237 @@ class TestBenchmarkBigo < MiniTest::Test
11
12
  $stdout = @old_stdout
12
13
  end
13
14
 
14
- def test_bigo
15
- #skip('pass')
15
+ def test_bigo_defaults
16
+ report = Benchmark.bigo do |x|
17
+ x.config(:time => 1, :warmup => 1)
18
+ x.generate :array
19
+
20
+ # size 100 will sleep for .1 seconds, size 200 will sleep for .2 seconds
21
+ x.report("sleep") { |_, size| sleep(size / 1000.0) }
22
+ end
23
+
24
+ assert_equal 1, report.entries.keys.length
25
+ rep = report.entries["sleep"]
26
+
27
+ assert_equal 10, rep.size
28
+
29
+ 10.times do |i|
30
+ size = 100 + i*100
31
+ assert_equal "sleep #{size}", rep[i].label
32
+
33
+ iterations = 1000.0 / size
34
+ assert_equal iterations.ceil, rep[i].iterations
35
+ assert_in_delta iterations, rep[i].ips, 0.4
36
+ end
37
+ end
38
+
39
+ def test_bigo_config_options
16
40
 
17
41
  report = Benchmark.bigo do |x|
18
- x.config(:time => 1, :warmup => 1, :increments => 2)
42
+ x.config(:time => 1, :warmup => 1,
43
+ :steps => 3, :step_size => 200, :min_size => 50)
19
44
  x.generate :array
20
45
 
21
46
  x.report("#at") {|array, size| array.at rand(size) }
22
- x.report("#index") {|array, size| array.index rand(size) }
23
- x.report("sleep") { |a,b| sleep(0.25) }
47
+
48
+ # size 100 will sleep for .1 seconds, size 200 will sleep for .2 seconds
49
+ x.report("sleep") { |_, size| sleep(size / 1000.0) }
24
50
  end
25
51
 
26
- assert_equal 3, report.entries.length
52
+ assert_equal 2, report.entries.length
27
53
 
28
54
  assert report.entries.keys.include?("#at")
29
- assert report.entries.keys.include?("#index")
30
55
  assert report.entries.keys.include?("sleep")
31
56
 
32
57
  at_rep = report.entries["#at"]
33
- index_rep = report.entries["#index"]
34
58
  sleep_rep = report.entries["sleep"]
35
59
 
36
- assert_equal 2, at_rep.size
37
- assert_equal 2, index_rep.size
38
- assert_equal 2, sleep_rep.size
60
+ assert_equal 3, at_rep.size
61
+ assert_equal 3, sleep_rep.size
39
62
 
40
- assert_equal "#at 100", at_rep[0].label
41
- assert_equal "#at 200", at_rep[1].label
63
+ assert_equal "#at 50", at_rep[0].label
64
+ assert_equal "#at 250", at_rep[1].label
65
+ assert_equal "#at 450", at_rep[2].label
42
66
 
43
- assert_equal "#index 100", index_rep[0].label
44
- assert_equal "#index 200", index_rep[1].label
67
+ assert_equal "sleep 50", sleep_rep[0].label
68
+ assert_equal "sleep 250", sleep_rep[1].label
69
+ assert_equal "sleep 450", sleep_rep[2].label
45
70
 
46
- assert_equal "sleep 100", sleep_rep[0].label
47
- assert_equal "sleep 200", sleep_rep[1].label
71
+ assert_equal 20, sleep_rep[0].iterations
72
+ assert_in_delta 20.0, sleep_rep[0].ips, 0.6
48
73
 
49
- assert_equal 4, sleep_rep[0].iterations
50
- assert_in_delta 4.0, sleep_rep[0].ips, 0.2
74
+ assert_equal 4, sleep_rep[1].iterations
75
+ assert_in_delta 4.0, sleep_rep[1].ips, 0.2
51
76
 
52
77
  end
53
78
 
54
- def test_bigo_alternate_config
55
- #skip('pass')
79
+ def test_bigo_setters
56
80
  report = Benchmark.bigo do |x|
57
81
  x.time = 1
58
82
  x.warmup = 1
59
- x.increments = 2
60
- x.generate(:array)
61
- x.report("sleep") { |a,b| sleep(0.25) }
83
+ x.steps = 3
84
+ x.step_size = 200
85
+ x.min_size = 50
86
+ x.generate :array
87
+
88
+ x.report("#at") {|array, size| array.at rand(size) }
89
+
90
+ # size 100 will sleep for .1 seconds, size 200 will sleep for .2 seconds
91
+ x.report("sleep") { |_, size| sleep(size / 1000.0) }
62
92
  end
63
93
 
64
- rep = report.entries["sleep"]
65
- assert_equal 2, rep.size
94
+ assert_equal 2, report.entries.length
66
95
 
67
- assert_equal "sleep 100", rep[0].label
68
- assert_equal 4, rep[0].iterations
69
- assert_in_delta 4.0, rep[0].ips, 0.2
70
- end
96
+ assert report.entries.keys.include?("#at")
97
+ assert report.entries.keys.include?("sleep")
71
98
 
72
- def test_bigo_defaults
73
- #skip('pass')
74
- report = Benchmark.bigo do |x|
75
- x.config(:time => 1, :warmup => 1)
76
- x.generate :array
77
- x.report("sleep") { |a,b| sleep(0.25) }
78
- end
99
+ at_rep = report.entries["#at"]
100
+ sleep_rep = report.entries["sleep"]
79
101
 
80
- assert_equal 1, report.entries.keys.length
81
- rep = report.entries["sleep"]
102
+ assert_equal 3, at_rep.size
103
+ assert_equal 3, sleep_rep.size
82
104
 
83
- assert_equal 5, rep.size
105
+ assert_equal "#at 50", at_rep[0].label
106
+ assert_equal "#at 250", at_rep[1].label
107
+ assert_equal "#at 450", at_rep[2].label
84
108
 
85
- assert_equal "sleep 100", rep[0].label
86
- assert_equal "sleep 200", rep[1].label
87
- assert_equal "sleep 300", rep[2].label
88
- assert_equal "sleep 400", rep[3].label
89
- assert_equal "sleep 500", rep[4].label
109
+ assert_equal "sleep 50", sleep_rep[0].label
110
+ assert_equal "sleep 250", sleep_rep[1].label
111
+ assert_equal "sleep 450", sleep_rep[2].label
90
112
 
91
- assert_equal 4, rep[0].iterations
92
- assert_in_delta 4.0, rep[0].ips, 0.2
113
+ assert_equal 20, sleep_rep[0].iterations
114
+ assert_in_delta 20.0, sleep_rep[0].ips, 0.6
115
+
116
+ assert_equal 4, sleep_rep[1].iterations
117
+ assert_in_delta 4.0, sleep_rep[1].ips, 0.2
93
118
  end
94
119
 
95
- def test_bigo_exponential
96
- #skip('pass')
120
+ def test_bigo_generate_json
121
+ json_file = Tempfile.new 'data.json'
97
122
  report = Benchmark.bigo do |x|
98
- x.config(:time => 1, :warmup => 1, :increments => 2)
123
+ x.config(:time => 1, :warmup => 1, :steps => 2)
99
124
  x.generate :array
100
- x.exponential
101
- x.report("sleep") { |a,b| sleep(0.25) }
125
+
126
+ x.report("#at") {|array, size| array.at rand(size) }
127
+ x.json! json_file.path
102
128
  end
103
129
 
104
- rep = report.entries["sleep"]
130
+ json_data = json_file.read
131
+ assert json_data
132
+ data = JSON.parse json_data
133
+ assert data
134
+ assert_equal 1, data.size
135
+ assert_equal "#at", data[0]["name"]
136
+ assert data[0]["data"]
137
+ assert data[0]["data"]["100"]
138
+ assert data[0]["data"]["200"]
139
+ end
105
140
 
106
- assert_equal "sleep 1", rep[0].label
107
- assert_equal "sleep 10", rep[1].label
108
- assert_equal 4, rep[0].iterations
109
- assert_in_delta 4.0, rep[0].ips, 0.2
141
+ def test_bigo_generate_csv
142
+ csv_file = Tempfile.new 'data.csv'
143
+ report = Benchmark.bigo do |x|
144
+ x.config(:time => 1, :warmup => 1, :steps => 2)
145
+ x.generate :array
146
+
147
+ x.report("#at") {|array, size| array.at rand(size) }
148
+ x.csv! csv_file.path
149
+ end
150
+ data = CSV.read(csv_file.path)
151
+ assert data
152
+ assert_equal 2, data.size
153
+ assert_equal ['','100', '200'], data[0]
154
+ assert_equal "#at", data[1][0]
155
+ assert_equal data[1][0].size, 3
110
156
  end
111
157
 
112
- def test_bigo_increments_config
113
- #skip('pass')
158
+ def test_bigo_generate_chart
159
+ chart_file = Tempfile.new 'data.html'
114
160
  report = Benchmark.bigo do |x|
115
- x.config(:time => 1, :warmup => 1, :increments => 3)
161
+ x.config(:time => 1, :warmup => 1, :steps => 2)
116
162
  x.generate :array
117
163
 
118
164
  x.report("#at") {|array, size| array.at rand(size) }
165
+ x.chart! chart_file.path
166
+ x.compare!
119
167
  end
120
168
 
121
- assert_equal 1, report.entries.length
169
+ data = File.read(chart_file.path)
170
+ assert data
171
+ assert data.match('<h1>Growth Chart</h1>')
172
+ assert data.match('<h1>#at</h1>')
173
+ end
174
+
175
+ def test_generate_array
122
176
 
123
- assert report.entries.keys.include?("#at")
177
+ job = Benchmark::BigO::Job.new({:suite => nil,
178
+ :quiet => true})
124
179
 
125
- at_rep = report.entries["#at"]
180
+ job.generate :array
126
181
 
127
- assert_equal 3, at_rep.size
182
+ job.report('test') {|array, size| array.at rand(size) }
183
+
184
+ # should create 10 job entries
185
+ assert_equal 10, job.list.size
128
186
 
129
- assert_equal "#at 100", at_rep[0].label
130
- assert_equal "#at 200", at_rep[1].label
131
- assert_equal "#at 300", at_rep[2].label
187
+ # the generated object should be an Array
188
+ assert Array === job.list.first.generated
189
+
190
+ # the Array should have 100 elements
191
+ assert_equal 100, job.list.first.generated.size
192
+
193
+ # when sorted, the array should equal 0...100
194
+ assert_equal (0...100).to_a, job.list.first.generated.sort
132
195
  end
133
196
 
134
- def test_bigo_increments_setter
135
- #skip('pass')
136
- report = Benchmark.bigo do |x|
137
- x.config(:time => 1, :warmup => 1)
138
- x.increments = 3
139
- x.generate :array
197
+ def test_generate_string
140
198
 
141
- x.report("#at") {|array, size| array.at rand(size) }
142
- end
199
+ job = Benchmark::BigO::Job.new({:suite => nil,
200
+ :quiet => true})
143
201
 
144
- assert_equal 1, report.entries.length
202
+ job.generate :string
145
203
 
146
- assert report.entries.keys.include?("#at")
204
+ job.report('test') {|string, size| string[rand(size)] }
147
205
 
148
- at_rep = report.entries["#at"]
206
+ # should create 10 job entries
207
+ assert_equal 10, job.list.size
149
208
 
150
- assert_equal 3, at_rep.size
209
+ # the generated object should be a String
210
+ assert String === job.list.first.generated
211
+
212
+ # the String should have length 100
213
+ assert_equal 200, job.list.first.generated.length
214
+ end
215
+
216
+ def test_generate_size
217
+ job = Benchmark::BigO::Job.new({:suite => nil,
218
+ :quiet => true})
219
+
220
+ job.generate :size
221
+
222
+ job.report('test') {|size, _| size.to_i }
223
+
224
+ # should create 10 job entries
225
+ assert_equal 10, job.list.size
226
+
227
+ # the generated object should be an Integer
228
+ assert Integer === job.list.first.generated
229
+
230
+ # the Integer should be the size
231
+ assert_equal 100, job.list.first.generated
232
+ assert_equal 1000, job.list[-1].generated
233
+
234
+ end
235
+
236
+ def test_step
237
+ job = Benchmark::BigO::Job.new({:suite => nil,
238
+ :quiet => true})
239
+
240
+ job.min_size = 22
241
+ job.steps = 6
242
+ job.step_size = 10
151
243
 
152
- assert_equal "#at 100", at_rep[0].label
153
- assert_equal "#at 200", at_rep[1].label
154
- assert_equal "#at 300", at_rep[2].label
244
+ assert_equal 22, job.step(0)
245
+ assert_equal 32, job.step(1)
246
+ assert_equal 42, job.step(2)
155
247
  end
156
248
  end