benchmarker 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.
- checksums.yaml +7 -0
- data/CHANGES.md +9 -0
- data/MIT-LICENSE +20 -0
- data/README.md +26 -0
- data/Rakefile +107 -0
- data/benchmarker.gemspec +20 -34
- data/lib/benchmarker.rb +1041 -0
- data/test/benchmarker_test.rb +1532 -560
- metadata +53 -79
- data/CHANGES.txt +0 -6
- data/examples/bench_loop.rb +0 -51
- data/examples/bench_require.rb +0 -34
- data/test/oktest.rb +0 -825
data/test/benchmarker_test.rb
CHANGED
@@ -1,694 +1,1666 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
###
|
2
|
-
### $Release:
|
3
|
-
### $Copyright: copyright(c) 2010-
|
4
|
-
### $License:
|
5
|
+
### $Release: 1.0.0 $
|
6
|
+
### $Copyright: copyright(c) 2010-2021 kuwata-lab.com all rights reserved $
|
7
|
+
### $License: MIT License $
|
5
8
|
###
|
6
9
|
|
7
|
-
|
8
|
-
$:.unshift File.class_eval { expand_path(join(dirname(__FILE__), '../lib')) }
|
10
|
+
$LOAD_PATH.unshift File.class_eval { join(dirname(dirname(__FILE__)), 'lib') }
|
9
11
|
|
10
12
|
require 'oktest'
|
13
|
+
|
14
|
+
BENCHMARKER_IGNORE_CMDOPTS = true
|
11
15
|
require 'benchmarker'
|
12
16
|
|
13
17
|
|
14
|
-
|
15
|
-
|
18
|
+
Oktest.scope do
|
19
|
+
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
+ topic(Benchmarker) do
|
22
|
+
|
23
|
+
+ topic('.new()') do
|
24
|
+
- spec("[!2zh7w] creates new Benchmark object wit options..") do
|
25
|
+
bm = Benchmarker.new()
|
26
|
+
ok {bm}.is_a?(Benchmarker::Benchmark)
|
27
|
+
ok {bm.width} == 30
|
28
|
+
ok {bm.loop} == 1
|
29
|
+
ok {bm.iter} == 1
|
30
|
+
ok {bm.extra} == 0
|
31
|
+
ok {bm.inverse} == false
|
32
|
+
ok {bm.outfile} == nil
|
33
|
+
#
|
34
|
+
bm = Benchmarker.new(width: 25, loop: 100, iter: 3, extra: 2, inverse: true, outfile: "tmp.js")
|
35
|
+
ok {bm}.is_a?(Benchmarker::Benchmark)
|
36
|
+
ok {bm.width} == 25
|
37
|
+
ok {bm.loop} == 100
|
38
|
+
ok {bm.iter} == 3
|
39
|
+
ok {bm.extra} == 2
|
40
|
+
ok {bm.inverse} == true
|
41
|
+
ok {bm.outfile} == "tmp.js"
|
42
|
+
end
|
43
|
+
- spec("[!s7y6x] overwrites existing options by command-line options.") do
|
44
|
+
kws = {width: 15, loop: 1000, iter: 20, extra: 3, inverse: true, outfile: "tmp2.js"}
|
45
|
+
bm = dummy_values(Benchmarker::OPTIONS, **kws) {
|
46
|
+
Benchmarker.new()
|
47
|
+
}
|
48
|
+
ok {bm}.is_a?(Benchmarker::Benchmark)
|
49
|
+
ok {bm.width} == 15
|
50
|
+
ok {bm.loop} == 1000
|
51
|
+
ok {bm.iter} == 20
|
52
|
+
ok {bm.extra} == 3
|
53
|
+
ok {bm.inverse} == true
|
54
|
+
ok {bm.outfile} == "tmp2.js"
|
55
|
+
end
|
21
56
|
end
|
22
|
-
end
|
23
57
|
|
24
|
-
|
25
|
-
spec
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
58
|
+
+ topic('.scope()') do
|
59
|
+
- spec("[!4f695] creates Benchmark object, define tasks, and run them.") do
|
60
|
+
this = self
|
61
|
+
sout, serr = capture_sio do
|
62
|
+
Benchmarker.scope() do
|
63
|
+
this.ok {self}.is_a?(Benchmarker::Scope)
|
64
|
+
task "1+1" do
|
65
|
+
1+1
|
66
|
+
end
|
67
|
+
task "1-1" do
|
68
|
+
1-1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
ok {serr} == ""
|
73
|
+
ok {sout} =~ /^## benchmarker: *release \d+.\d+.\d+$/
|
74
|
+
ok {sout} =~ /^## Ranking/
|
75
|
+
ok {sout} =~ /^1\+1 +0\./
|
76
|
+
ok {sout} =~ /^1\-1 +0\./
|
77
|
+
ok {sout} =~ /^## Matrix/
|
78
|
+
end
|
40
79
|
end
|
41
|
-
end
|
42
80
|
|
43
|
-
end
|
81
|
+
end
|
44
82
|
|
45
83
|
|
46
|
-
|
47
|
-
include Oktest::TestCase
|
84
|
+
+ topic(Benchmarker::Benchmark) do
|
48
85
|
|
49
|
-
|
50
|
-
|
51
|
-
runner = Benchmarker::RUNNER.new(:loop=>10, :cycle=>20, :extra=>30)
|
52
|
-
ok {runner.instance_variable_get('@loop')} == 10
|
53
|
-
ok {runner.instance_variable_get('@cycle')} == 20
|
54
|
-
ok {runner.instance_variable_get('@extra')} == 30
|
86
|
+
fixture :bm do
|
87
|
+
Benchmarker::Benchmark.new
|
55
88
|
end
|
56
|
-
end
|
57
89
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
spec "prints section title if not printed yet." do
|
68
|
-
ok {sout} =~ /\A\n## {28} user sys total real\n.*\n/
|
69
|
-
ok {serr} == ""
|
70
|
-
end
|
71
|
-
spec "creates task objet and returns it." do
|
72
|
-
ok {ret}.is_a?(Benchmarker::TASK)
|
73
|
-
end
|
74
|
-
spec "saves created task object unless :skip optin is not specified." do
|
75
|
-
task = ret
|
76
|
-
ok {runner.tasks} == [task]
|
77
|
-
end
|
78
|
-
spec "runs task when :skip option is not specified." do
|
79
|
-
ok {called} == true
|
80
|
-
ok {sout} =~ /\A\n.*\nlabel1 0\.\d+ 0\.\d+ 0\.\d+ 0\.\d+\n/
|
81
|
-
end
|
82
|
-
spec "skip block and prints message when :skip option is specified." do
|
83
|
-
ok {sout} =~ /^label2 *\# not installed\.\n/
|
84
|
-
end
|
85
|
-
spec "subtracts times of empty task if exists." do
|
86
|
-
empty_task = runner.empty_task { nil }
|
87
|
-
empty_task.user = 10.0
|
88
|
-
empty_task.sys = 5.0
|
89
|
-
empty_task.total = 15.0
|
90
|
-
empty_task.real = 20.0
|
91
|
-
t = runner.task("label2") { x = 1+1 }
|
92
|
-
ok {t.user }.in_delta?(-10.0, 0.1)
|
93
|
-
ok {t.sys }.in_delta?(- 5.0, 0.1)
|
94
|
-
ok {t.total}.in_delta?(-15.0, 0.1)
|
95
|
-
ok {t.real }.in_delta?(-20.0, 0.1)
|
90
|
+
+ topic('#initialize()') do
|
91
|
+
- spec("[!0mz0f] error when filter string is invalid format.") do
|
92
|
+
pr = proc { Benchmarker::Benchmark.new(filter: 'foobar') }
|
93
|
+
ok {pr}.raise?(ArgumentError, "foobar: invalid filter.")
|
94
|
+
end
|
95
|
+
- spec("[!xo7bq] error when filter operator is invalid.") do
|
96
|
+
pr = proc { Benchmarker::Benchmark.new(filter: 'task==foobar') }
|
97
|
+
ok {pr}.raise?(ArgumentError, "task==foobar: expected operator is '=' or '!='.")
|
98
|
+
end
|
96
99
|
end
|
97
|
-
end
|
98
100
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
101
|
+
+ topic('#clear()') do
|
102
|
+
- spec("[!phqdn] clears benchmark result and JSON data.") do |bm|
|
103
|
+
bm.scope do
|
104
|
+
task "foo" do nil end
|
105
|
+
task "bar" do nil end
|
106
|
+
end
|
107
|
+
capture_sio { bm.run() }
|
108
|
+
result_foo = bm.instance_eval{@entries[0][1]}
|
109
|
+
result_bar = bm.instance_eval{@entries[1][1]}
|
110
|
+
ok {result_foo.length} == 1
|
111
|
+
ok {result_bar.length} == 1
|
112
|
+
#
|
113
|
+
bm.clear()
|
114
|
+
ok {result_foo.length} == 0
|
115
|
+
ok {result_bar.length} == 0
|
105
116
|
end
|
106
|
-
ok {task}.is_a?(Benchmarker::TASK)
|
107
|
-
ok {task.label} == "(Empty)"
|
108
|
-
end
|
109
|
-
spec "prints section title if not printed yet." do
|
110
|
-
ok {sout} =~ /^## +user +sys +total +real\n/
|
111
|
-
end
|
112
|
-
spec "saves empty task object." do
|
113
|
-
ok {runner.instance_variable_get('@_empty_task')} == task
|
114
117
|
end
|
115
|
-
|
116
|
-
|
118
|
+
|
119
|
+
+ topic('#scope()') do
|
120
|
+
- spec("[!wrjy0] creates wrapper object and yields block with it as self.") do |bm|
|
121
|
+
this = self
|
122
|
+
ret = bm.scope() do |*args|
|
123
|
+
this.ok {self} != this
|
124
|
+
this.ok {self}.is_a?(Benchmarker::Scope)
|
125
|
+
this.ok {self}.respond_to?(:task)
|
126
|
+
this.ok {self}.respond_to?(:empty_task)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
- spec("[!6h24d] passes benchmark object as argument of block.") do |bm|
|
130
|
+
this = self
|
131
|
+
bm.scope() do |*args|
|
132
|
+
this.ok {args} == [bm]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
- spec("[!y0uwr] returns self.") do |bm|
|
136
|
+
ret = bm.scope() do nil end
|
137
|
+
ok {ret}.same?(bm)
|
138
|
+
end
|
117
139
|
end
|
118
|
-
|
119
|
-
|
140
|
+
|
141
|
+
+ topic('#define_empty_task()') do
|
142
|
+
- spec("[!w66xp] creates empty task.") do |bm|
|
143
|
+
ok {bm.instance_eval{@empty_task}} == nil
|
144
|
+
ret = bm.define_empty_task() do nil end
|
145
|
+
ok {bm.instance_eval{@empty_task}} != nil
|
146
|
+
ok {bm.instance_eval{@empty_task}}.is_a?(Benchmarker::Task)
|
147
|
+
ok {bm.instance_eval{@empty_task}.name} == nil
|
148
|
+
ok {ret}.is_a?(Benchmarker::Task)
|
149
|
+
ok {ret.name} == nil
|
150
|
+
end
|
151
|
+
- spec("[!qzr1s] error when called more than once.") do |bm|
|
152
|
+
pr = proc { bm.define_empty_task() do nil end }
|
153
|
+
ok {pr}.NOT.raise?()
|
154
|
+
ok {pr}.raise?(RuntimeError, "cannot define empty task more than once.")
|
155
|
+
end
|
120
156
|
end
|
121
|
-
end
|
122
157
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
158
|
+
+ topic('#define_task()') do
|
159
|
+
- spec("[!re6b8] creates new task.") do |bm|
|
160
|
+
ret = bm.define_task("foobar") do nil end
|
161
|
+
ok {ret}.is_a?(Benchmarker::Task)
|
162
|
+
ok {ret.name} == "foobar"
|
163
|
+
end
|
164
|
+
- spec("[!r8o0p] can take a tag.") do |bm|
|
165
|
+
ret = bm.define_task("balbla", tag: 'curr') do nil end
|
166
|
+
ok {ret.tag} == "curr"
|
167
|
+
end
|
129
168
|
end
|
130
|
-
|
131
|
-
|
169
|
+
|
170
|
+
+ topic('#define_hook()') do |bm|
|
171
|
+
- spec("[!2u53t] register proc object with symbol key.") do |bm|
|
172
|
+
called = false
|
173
|
+
bm.define_hook(:hook1) do called = true end
|
174
|
+
ok {called} == false
|
175
|
+
bm.__send__(:call_hook, :hook1)
|
176
|
+
ok {called} == true
|
177
|
+
end
|
132
178
|
end
|
133
|
-
|
134
|
-
|
135
|
-
|
179
|
+
|
180
|
+
+ topic('#call_hook()') do |bm|
|
181
|
+
- spec("[!0to2s] calls hook with arguments.") do |bm|
|
182
|
+
args = nil
|
183
|
+
bm.define_hook(:hook2) do |*a| args = a end
|
184
|
+
ok {args} == nil
|
185
|
+
bm.__send__(:call_hook, :hook2, "abc", tag: "xyz")
|
186
|
+
ok {args} == ["abc", {tag: "xyz"}]
|
187
|
+
end
|
136
188
|
end
|
137
|
-
|
138
|
-
|
189
|
+
|
190
|
+
+ topic('#run()') do
|
191
|
+
- spec("[!0fo0l] runs benchmark tasks and reports result.") do |bm|
|
192
|
+
foo_called = false; bar_called = false
|
193
|
+
bm.define_task("foo") do foo_called = true end
|
194
|
+
bm.define_task("bar") do bar_called = true end
|
195
|
+
ok {foo_called} == false
|
196
|
+
ok {bar_called} == false
|
197
|
+
sout, serr = capture_sio do
|
198
|
+
bm.run()
|
199
|
+
end
|
200
|
+
ok {foo_called} == true
|
201
|
+
ok {bar_called} == true
|
202
|
+
ok {serr} == ""
|
203
|
+
ok {sout} =~ /^\#\# benchmarker:/
|
204
|
+
ok {sout} =~ /^foo +/
|
205
|
+
ok {sout} =~ /^bar +/
|
206
|
+
end
|
207
|
+
- spec("[!6h26u] runs preriminary round when `warmup: true` provided.") do |bm|
|
208
|
+
called = 0
|
209
|
+
bm.define_task("foo") do called += 1 end
|
210
|
+
sout, serr = capture_sio do
|
211
|
+
bm.run(warmup: true)
|
212
|
+
end
|
213
|
+
ok {called} == 2
|
214
|
+
n = 0
|
215
|
+
sout.scan(/^## +.*\nfoo +/) { n += 1 }
|
216
|
+
ok {n} == 1
|
217
|
+
end
|
218
|
+
- spec("[!2j4ks] calls 'before_all' hook.") do |bm|
|
219
|
+
called = 0
|
220
|
+
bm.define_hook(:before_all) do called += 1 end
|
221
|
+
ok {called} == 0
|
222
|
+
capture_sio { bm.run() }
|
223
|
+
ok {called} == 1
|
224
|
+
end
|
225
|
+
- spec("[!w1rq7] calls 'after_all' hook even if error raised.") do |bm|
|
226
|
+
called = 0
|
227
|
+
bm.define_hook(:after_all) do called += 1 end
|
228
|
+
bm.define_task("foo") do 1/0 end # raises ZeroDivisionError
|
229
|
+
ok {called} == 0
|
230
|
+
capture_sio do
|
231
|
+
pr = proc { bm.run() }
|
232
|
+
ok {pr}.raise?(ZeroDivisionError)
|
233
|
+
end
|
234
|
+
ok {called} == 1
|
235
|
+
end
|
139
236
|
end
|
140
|
-
end
|
141
237
|
|
142
|
-
|
143
|
-
spec
|
144
|
-
|
145
|
-
|
146
|
-
|
238
|
+
+ topic('#_ignore_output()') do
|
239
|
+
- spec("[!wazs7] ignores output in block argument.") do |bm|
|
240
|
+
called = false
|
241
|
+
sout, serr = capture_sio do
|
242
|
+
puts "aaa"
|
243
|
+
bm.__send__(:_ignore_output) do
|
244
|
+
puts "bbb"
|
245
|
+
called = true
|
246
|
+
end
|
247
|
+
puts "ccc"
|
248
|
+
end
|
249
|
+
ok {called} == true
|
250
|
+
ok {sout} == "aaa\nccc\n"
|
251
|
+
ok {serr} == ""
|
147
252
|
end
|
148
|
-
ok {sout} == Benchmarker.platform()
|
149
253
|
end
|
150
|
-
end
|
151
254
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
255
|
+
+ topic('#filter_tasks()') do
|
256
|
+
def new_bm(filter)
|
257
|
+
bm = Benchmarker::Benchmark.new(filter: filter).scope do
|
258
|
+
task "foo" do nil end
|
259
|
+
task "bar", tag: 'xx' do nil end
|
260
|
+
task "baz", tag: ['xx', 'yy'] do nil end
|
261
|
+
end
|
262
|
+
bm
|
263
|
+
end
|
264
|
+
def task_names(bm)
|
265
|
+
bm.instance_eval {@entries}.collect {|t,_| t.name}
|
266
|
+
end
|
267
|
+
- spec("[!f1n1v] filters tasks by task name when filer string is 'task=...'.") do
|
268
|
+
bm = new_bm('task=bar')
|
269
|
+
ok {task_names(bm)} == ["foo", "bar", "baz"]
|
270
|
+
bm.__send__(:filter_tasks)
|
271
|
+
ok {task_names(bm)} == ["bar"]
|
272
|
+
#
|
273
|
+
bm = new_bm('task=ba*')
|
274
|
+
ok {task_names(bm)} == ["foo", "bar", "baz"]
|
275
|
+
bm.__send__(:filter_tasks)
|
276
|
+
ok {task_names(bm)} == ["bar", "baz"]
|
277
|
+
#
|
278
|
+
bm = new_bm('task=*z')
|
279
|
+
ok {task_names(bm)} == ["foo", "bar", "baz"]
|
280
|
+
bm.__send__(:filter_tasks)
|
281
|
+
ok {task_names(bm)} == ["baz"]
|
282
|
+
#
|
283
|
+
bm = new_bm('task=*xx*')
|
284
|
+
ok {task_names(bm)} == ["foo", "bar", "baz"]
|
285
|
+
bm.__send__(:filter_tasks)
|
286
|
+
ok {task_names(bm)} == []
|
287
|
+
end
|
288
|
+
- spec("[!m79cf] filters tasks by tag value when filer string is 'tag=...'.") do
|
289
|
+
bm = new_bm('tag=xx')
|
290
|
+
bm.__send__(:filter_tasks)
|
291
|
+
ok {task_names(bm)} == ["bar", "baz"]
|
292
|
+
#
|
293
|
+
bm = new_bm('tag=yy')
|
294
|
+
bm.__send__(:filter_tasks)
|
295
|
+
ok {task_names(bm)} == ["baz"]
|
296
|
+
#
|
297
|
+
bm = new_bm('tag=*x')
|
298
|
+
bm.__send__(:filter_tasks)
|
299
|
+
ok {task_names(bm)} == ["bar", "baz"]
|
300
|
+
#
|
301
|
+
bm = new_bm('tag=zz')
|
302
|
+
bm.__send__(:filter_tasks)
|
303
|
+
ok {task_names(bm)} == []
|
304
|
+
end
|
305
|
+
- spec("[!0in0q] supports negative filter by '!=' operator.") do
|
306
|
+
bm = new_bm('task!=bar')
|
307
|
+
bm.__send__(:filter_tasks)
|
308
|
+
ok {task_names(bm)} == ["foo", "baz"]
|
309
|
+
#
|
310
|
+
bm = new_bm('task!=ba*')
|
311
|
+
bm.__send__(:filter_tasks)
|
312
|
+
ok {task_names(bm)} == ["foo"]
|
313
|
+
#
|
314
|
+
bm = new_bm('tag!=xx')
|
315
|
+
bm.__send__(:filter_tasks)
|
316
|
+
ok {task_names(bm)} == ["foo"]
|
317
|
+
#
|
318
|
+
bm = new_bm('tag!=yy')
|
319
|
+
bm.__send__(:filter_tasks)
|
320
|
+
ok {task_names(bm)} == ["foo", "bar"]
|
321
|
+
end
|
322
|
+
- spec("[!g207d] do nothing when filter string is not provided.") do
|
323
|
+
bm = new_bm(nil)
|
324
|
+
bm.__send__(:filter_tasks)
|
325
|
+
ok {task_names(bm)} == ["foo", "bar", "baz"]
|
161
326
|
end
|
162
|
-
ok {tr[0].name} == :all
|
163
|
-
ok {sout} =~ /^## Ranking/
|
164
|
-
ok {sout} =~ /^## Matrix/
|
165
327
|
end
|
166
|
-
end
|
167
328
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
329
|
+
+ topic('#invoke_tasks()') do
|
330
|
+
def new_bm(**kwargs)
|
331
|
+
called = []
|
332
|
+
bm = Benchmarker::Benchmark.new(**kwargs).scope do
|
333
|
+
empty_task do called << :empty end
|
334
|
+
task "foo" do called << :foo end
|
335
|
+
task "bar" do called << :bar end
|
336
|
+
task "baz" do called << :baz end
|
337
|
+
end
|
338
|
+
return bm, called
|
339
|
+
end
|
340
|
+
class Task2 < Benchmarker::Task
|
341
|
+
def invoke(loop=1)
|
342
|
+
super
|
343
|
+
case @name
|
344
|
+
when nil ; a = [0.002, 0.001, 0.003, 0.0031]
|
345
|
+
when "foo" ; a = [0.005, 0.003, 0.008, 0.0085]
|
346
|
+
when "bar" ; a = [0.007, 0.004, 0.011, 0.0115]
|
347
|
+
when "baz" ; a = [0.009, 0.005, 0.014, 0.0145]
|
348
|
+
else ; raise "** internal error"
|
180
349
|
end
|
350
|
+
Benchmarker::TimeSet.new(*a)
|
181
351
|
end
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
352
|
+
end
|
353
|
+
def with_dummy_task_class()
|
354
|
+
Benchmarker.module_eval { remove_const :TASK; const_set :TASK, Task2 }
|
355
|
+
yield
|
356
|
+
ensure
|
357
|
+
Benchmarker.module_eval { remove_const :TASK; const_set :TASK, Benchmarker::Task }
|
358
|
+
end
|
359
|
+
- spec("[!3hgos] invokes empty task at first if defined.") do
|
360
|
+
bm, called = new_bm()
|
361
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
362
|
+
ok {called.first} == :empty
|
363
|
+
ok {sout} =~ /^## +.*\n\(Empty\) +/
|
364
|
+
end
|
365
|
+
- spec("[!xf84h] invokes all tasks.") do
|
366
|
+
bm, called = new_bm()
|
367
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
368
|
+
ok {called} == [:empty, :foo, :bar, :baz]
|
369
|
+
ok {sout} =~ /^\(Empty\) +.*\nfoo +.*\nbar +.*\nbaz +.*\n/
|
370
|
+
end
|
371
|
+
- spec("[!6g36c] invokes task with validator if validator defined.") do
|
372
|
+
bm = Benchmarker::Benchmark.new().scope do
|
373
|
+
task "foo" do 100 end
|
374
|
+
task "bar" do 123 end
|
375
|
+
validate do |actual, name|
|
376
|
+
actual == 100 or
|
377
|
+
raise "task(#{name.inspect}): #{actual.inspect} == 100: failed."
|
194
378
|
end
|
195
379
|
end
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
ok {
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
ok {
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
380
|
+
pr = proc do
|
381
|
+
capture_sio { bm.__send__(:invoke_tasks) }
|
382
|
+
end
|
383
|
+
ok {pr}.raise?(RuntimeError, "task(\"bar\"): 123 == 100: failed.")
|
384
|
+
end
|
385
|
+
- spec("[!c8yak] invokes tasks once if 'iter' option not specified.") do
|
386
|
+
bm, called = new_bm(iter: nil)
|
387
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
388
|
+
ok {called} == [:empty, :foo, :bar, :baz] * 1
|
389
|
+
ok {sout} !~ /^## \(#\d\)/
|
390
|
+
end
|
391
|
+
- spec("[!unond] invokes tasks multiple times if 'iter' option specified.") do
|
392
|
+
bm, called = new_bm(iter: 5)
|
393
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
394
|
+
ok {called} == [:empty, :foo, :bar, :baz] * 5
|
395
|
+
ok {sout} =~ /^## \(#1\)/
|
396
|
+
ok {sout} =~ /^## \(#5\)/
|
397
|
+
end
|
398
|
+
- spec("[!wzvdb] invokes tasks 16 times if 'iter' is 10 and 'extra' is 3.") do
|
399
|
+
bm, called = new_bm(iter: 10, extra: 3)
|
400
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
401
|
+
ok {called} == [:empty, :foo, :bar, :baz] * 16
|
402
|
+
ok {sout} =~ /^## \(#1\)/
|
403
|
+
ok {sout} =~ /^## \(#16\)/
|
404
|
+
end
|
405
|
+
- spec("[!hbass] calls 'before' hook with task name and tag.") do
|
406
|
+
called = 0
|
407
|
+
argslist = []
|
408
|
+
bm = Benchmarker::Benchmark.new().scope do
|
409
|
+
before do |*a| called += 1; argslist << a end
|
410
|
+
task "foo" do nil end
|
411
|
+
task "bar", tag: 'yy' do nil end
|
412
|
+
end
|
413
|
+
ok {called} == 0
|
414
|
+
ok {argslist} == []
|
415
|
+
capture_sio { bm.__send__(:invoke_tasks) }
|
416
|
+
ok {called} == 2
|
417
|
+
ok {argslist} == [["foo", nil], ["bar", 'yy']]
|
418
|
+
end
|
419
|
+
- spec("[!7960c] calls 'after' hook with task name and tag even if error raised.") do
|
420
|
+
called = 0
|
421
|
+
argslist = []
|
422
|
+
bm = Benchmarker::Benchmark.new().scope do
|
423
|
+
after do |*a| called += 1; argslist << a end
|
424
|
+
task "foo" do nil end
|
425
|
+
task "bar", tag: 'yy' do 1/0 end # raises ZeroDivisionError
|
426
|
+
task "baz", tag: 'zz' do nil end
|
427
|
+
end
|
428
|
+
ok {called} == 0
|
429
|
+
ok {argslist} == []
|
430
|
+
capture_sio do
|
431
|
+
pr = proc { bm.__send__(:invoke_tasks) }
|
432
|
+
ok {pr}.raise?(ZeroDivisionError)
|
433
|
+
end
|
434
|
+
ok {called} == 2
|
435
|
+
ok {argslist} == [["foo", nil], ["bar", 'yy']]
|
436
|
+
end
|
437
|
+
- spec("[!fv4cv] skips task invocation if skip reason is specified.") do
|
438
|
+
called = []
|
439
|
+
bm = Benchmarker::Benchmark.new().scope do
|
440
|
+
empty_task do called << :empty end
|
441
|
+
task "foo" do called << :foo end
|
442
|
+
task "bar", skip: "not installed" do called << :bar end
|
443
|
+
task "baz" do called << :baz end
|
444
|
+
end
|
445
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
446
|
+
ok {called} == [:empty, :foo, :baz] # :bar is not included
|
447
|
+
end
|
448
|
+
- spec("[!dyofw] prints reason if 'skip:' option specified.") do
|
449
|
+
bm = Benchmarker::Benchmark.new().scope do
|
450
|
+
task "foo" do nil end
|
451
|
+
task "bar", skip: "not installed" do nil end
|
452
|
+
task "baz" do nil end
|
453
|
+
end
|
454
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
455
|
+
ok {sout} =~ /^bar +\# Skipped \(reason: not installed\)$/
|
456
|
+
end
|
457
|
+
- spec("[!ygpx0] records reason of skip into JSON data.") do
|
458
|
+
with_dummy_task_class do
|
459
|
+
bm = Benchmarker::Benchmark.new().scope do
|
460
|
+
task "foo" do nil end
|
461
|
+
task "bar", skip: "not installed" do nil end
|
462
|
+
task "baz" do nil end
|
228
463
|
end
|
464
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
465
|
+
ok {bm.instance_eval{@jdata}} == {
|
466
|
+
:Results => [
|
467
|
+
[
|
468
|
+
["foo", 0.005, 0.003, 0.008, 0.0085],
|
469
|
+
["bar", nil, nil, nil, nil, "not installed"],
|
470
|
+
["baz", 0.009, 0.005, 0.014, 0.0145],
|
471
|
+
]
|
472
|
+
]
|
473
|
+
}
|
229
474
|
end
|
230
|
-
ok {i} == 1
|
231
|
-
ok {sout} =~ /^## *user/
|
232
475
|
end
|
233
|
-
|
234
|
-
|
476
|
+
- spec("[!513ok] subtract timeset of empty loop from timeset of each task.") do
|
477
|
+
with_dummy_task_class do
|
478
|
+
bm, called = new_bm()
|
479
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
480
|
+
sout =~ /^foo +0\.0030 0\.0020 0\.0050 0\.0054$/
|
481
|
+
sout =~ /^bar +0\.0050 0\.0030 0\.0080 0\.0084$/
|
482
|
+
sout =~ /^baz +0\.0070 0\.0040 0\.0110 0\.0114$/
|
483
|
+
end
|
484
|
+
end
|
485
|
+
- spec("[!yg9i7] prints result unless quiet mode.") do
|
486
|
+
with_dummy_task_class do
|
487
|
+
bm, _ = new_bm()
|
488
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
489
|
+
ok {sout} =~ /^## .* +user sys total real$/
|
490
|
+
ok {sout} =~ /^\(Empty\) +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
491
|
+
ok {sout} =~ /^foo +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
492
|
+
ok {sout} =~ /^bar +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
493
|
+
ok {sout} =~ /^baz +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
494
|
+
end
|
495
|
+
end
|
496
|
+
- spec("[!94916] suppresses result if quiet mode.") do
|
497
|
+
with_dummy_task_class do
|
498
|
+
bm, _ = new_bm(quiet: true, iter: 2)
|
499
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
500
|
+
ok {sout} !~ /^## .* +user sys total real$/
|
501
|
+
ok {sout} !~ /^\(Empty\) +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
502
|
+
ok {sout} !~ /^foo +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
503
|
+
ok {sout} !~ /^bar +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
504
|
+
ok {sout} !~ /^baz +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
505
|
+
end
|
506
|
+
end
|
507
|
+
- spec("[!5axhl] prints result even on quiet mode if no 'iter' nor 'extra'.") do
|
508
|
+
with_dummy_task_class do
|
509
|
+
bm, _ = new_bm(quiet: true)
|
510
|
+
sout, serr = capture_sio { bm.__send__(:invoke_tasks) }
|
511
|
+
ok {sout} =~ /^## .* +user sys total real$/
|
512
|
+
ok {sout} =~ /^\(Empty\) +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
513
|
+
ok {sout} =~ /^foo +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
514
|
+
ok {sout} =~ /^bar +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
515
|
+
ok {sout} =~ /^baz +\d+\.\d+ +\d+\.\d+ +\d+\.\d+ +\d+\.\d+$/
|
516
|
+
end
|
517
|
+
end
|
518
|
+
- spec("[!knjls] records result of empty loop into JSON data.") do
|
519
|
+
with_dummy_task_class do
|
520
|
+
bm, _ = new_bm()
|
521
|
+
capture_sio { bm.__send__(:invoke_tasks) }
|
522
|
+
jdata = bm.instance_variable_get(:@jdata)
|
523
|
+
ok {jdata}.key?(:Results)
|
524
|
+
ok {jdata[:Results][0][0]} == ["(Empty)", 0.002, 0.001, 0.003, 0.0031]
|
525
|
+
end
|
526
|
+
end
|
527
|
+
- spec("[!ejxif] records result of each task into JSON data.") do
|
528
|
+
with_dummy_task_class do
|
529
|
+
bm, _ = new_bm()
|
530
|
+
capture_sio { bm.__send__(:invoke_tasks) }
|
531
|
+
jdata = bm.instance_variable_get(:@jdata)
|
532
|
+
ok {jdata}.key?(:Results)
|
533
|
+
ok {jdata[:Results]} == [
|
534
|
+
[
|
535
|
+
["(Empty)", 0.002, 0.001, 0.003, 0.0031],
|
536
|
+
["foo" , 0.003, 0.002, 0.005, 0.0054],
|
537
|
+
["bar" , 0.005, 0.003, 0.008, 0.0084],
|
538
|
+
["baz" , 0.007, 0.004, 0.011, 0.0114],
|
539
|
+
],
|
540
|
+
]
|
541
|
+
#
|
542
|
+
bm, _ = new_bm(iter: 3)
|
543
|
+
capture_sio { bm.__send__(:invoke_tasks) }
|
544
|
+
jdata = bm.instance_variable_get(:@jdata)
|
545
|
+
ok {jdata}.key?(:Results)
|
546
|
+
result = [
|
547
|
+
["(Empty)", 0.002, 0.001, 0.003, 0.0031],
|
548
|
+
["foo" , 0.003, 0.002, 0.005, 0.0054],
|
549
|
+
["bar" , 0.005, 0.003, 0.008, 0.0084],
|
550
|
+
["baz" , 0.007, 0.004, 0.011, 0.0114],
|
551
|
+
]
|
552
|
+
ok {jdata[:Results]} == [result, result, result]
|
553
|
+
end
|
554
|
+
end
|
555
|
+
- spec("[!vbhvz] sleeps N seconds after each task if `sleep` option specified.") do
|
556
|
+
new_bm = proc {|kwargs|
|
557
|
+
Benchmarker::Benchmark.new(**kwargs).scope do
|
558
|
+
empty_task do nil end
|
559
|
+
task "foo" do nil end
|
560
|
+
task "bar" do nil end
|
561
|
+
end
|
562
|
+
}
|
563
|
+
#
|
564
|
+
bm = new_bm.call({})
|
565
|
+
start = Time.now
|
566
|
+
capture_sio { bm.__send__(:invoke_tasks) }
|
567
|
+
ok {Time.now - start} < 0.1
|
568
|
+
#
|
569
|
+
bm = new_bm.call({sleep: 1})
|
570
|
+
start = Time.now
|
571
|
+
capture_sio { bm.__send__(:invoke_tasks) }
|
572
|
+
ok {Time.now - start} > 3.0
|
235
573
|
end
|
236
574
|
end
|
237
|
-
end
|
238
575
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
sos.call("Haruhi", 11.1, 0.2, 11.3, 11.9),
|
255
|
-
sos.call("Mikuru", 14.1, 0.2, 14.3, 14.2),
|
256
|
-
sos.call("Yuki", 10.1, 0.2, 10.3, 10.6),
|
257
|
-
sos.call("Itsuki", 12.1, 0.2, 12.3, 12.5),
|
258
|
-
sos.call("Kyon", 13.1, 0.2, 13.3, 13.3),
|
259
|
-
]
|
260
|
-
all_tasks << [
|
261
|
-
sos.call("Haruhi", 11.1, 0.2, 11.3, 11.5),
|
262
|
-
sos.call("Mikuru", 14.1, 0.2, 14.3, 14.8),
|
263
|
-
sos.call("Yuki", 10.1, 0.2, 10.3, 10.9),
|
264
|
-
sos.call("Itsuki", 12.1, 0.2, 12.3, 12.7),
|
265
|
-
sos.call("Kyon", 13.1, 0.2, 13.3, 13.9),
|
266
|
-
]
|
267
|
-
all_tasks << [
|
268
|
-
sos.call("Haruhi", 11.1, 0.2, 11.3, 11.3),
|
269
|
-
sos.call("Mikuru", 14.1, 0.2, 14.3, 14.2),
|
270
|
-
sos.call("Yuki", 10.1, 0.2, 10.3, 10.3),
|
271
|
-
sos.call("Itsuki", 12.1, 0.2, 12.3, 12.8),
|
272
|
-
sos.call("Kyon", 13.1, 0.2, 13.3, 13.4),
|
273
|
-
]
|
274
|
-
all_tasks << [
|
275
|
-
sos.call("Haruhi", 11.1, 0.2, 11.3, 11.6),
|
276
|
-
sos.call("Mikuru", 14.1, 0.2, 14.3, 14.2),
|
277
|
-
sos.call("Yuki", 10.1, 0.2, 10.3, 10.6),
|
278
|
-
sos.call("Itsuki", 12.1, 0.2, 12.3, 12.4),
|
279
|
-
sos.call("Kyon", 13.1, 0.2, 13.3, 13.3),
|
280
|
-
]
|
281
|
-
all_tasks << [
|
282
|
-
sos.call("Haruhi", 11.1, 0.2, 11.3, 11.3),
|
283
|
-
sos.call("Mikuru", 14.1, 0.2, 14.3, 14.8),
|
284
|
-
sos.call("Yuki", 10.1, 0.2, 10.3, 10.3),
|
285
|
-
sos.call("Itsuki", 12.1, 0.2, 12.3, 12.2),
|
286
|
-
sos.call("Kyon", 13.1, 0.2, 13.3, 13.7),
|
287
|
-
]
|
288
|
-
#
|
289
|
-
expected = <<'END'
|
290
|
-
|
291
|
-
## Remove Min & Max min cycle max cycle
|
292
|
-
Haruhi 11.3000 (#1) 11.9000 (#2)
|
293
|
-
11.3000 (#6) 11.6000 (#5)
|
294
|
-
Mikuru 14.1000 (#1) 14.8000 (#6)
|
295
|
-
14.2000 (#2) 14.8000 (#3)
|
296
|
-
Yuki 10.3000 (#6) 10.9000 (#3)
|
297
|
-
10.3000 (#4) 10.6000 (#5)
|
298
|
-
Itsuki 12.1000 (#1) 12.8000 (#4)
|
299
|
-
12.2000 (#6) 12.7000 (#3)
|
300
|
-
Kyon 13.3000 (#5) 13.9000 (#3)
|
301
|
-
13.3000 (#2) 13.7000 (#6)
|
302
|
-
|
303
|
-
## Average of 2 user sys total real
|
304
|
-
Haruhi 11.1000 0.2000 11.3000 11.4000
|
305
|
-
Mikuru 14.1000 0.2000 14.3000 14.2000
|
306
|
-
Yuki 10.1000 0.2000 10.3000 10.5000
|
307
|
-
Itsuki 12.1000 0.2000 12.3000 12.4500
|
308
|
-
Kyon 13.1000 0.2000 13.3000 13.4500
|
309
|
-
END
|
310
|
-
#
|
311
|
-
spec "calculates average times of tasks." do
|
312
|
-
avg_tasks = nil
|
313
|
-
sout, serr = dummy_io() do
|
314
|
-
runner = Benchmarker::RUNNER.new(:cycle=>2)
|
315
|
-
avg_tasks = runner.__send__(:_calc_averages, all_tasks, 2)
|
316
|
-
runner.__send__(:_report_average_section, avg_tasks)
|
576
|
+
+ topic('#ignore_skipped_tasks()') do
|
577
|
+
def task_names(bm)
|
578
|
+
bm.instance_eval {@entries}.collect {|t,_| t.name}
|
579
|
+
end
|
580
|
+
- spec("[!5gpo7] removes skipped tasks and leaves other tasks.") do
|
581
|
+
bm = Benchmarker::Benchmark.new().scope do
|
582
|
+
empty_task do nil end
|
583
|
+
task "foo", skip: "not installed" do nil end
|
584
|
+
task "bar", skip: "not installed" do nil end
|
585
|
+
task "baz" do nil end
|
586
|
+
end
|
587
|
+
capture_sio { bm.__send__(:invoke_tasks) }
|
588
|
+
ok {task_names(bm)} == ["foo", "bar", "baz"]
|
589
|
+
bm.__send__(:ignore_skipped_tasks)
|
590
|
+
ok {task_names(bm)} == ["baz"]
|
317
591
|
end
|
318
|
-
ok {sout} == expected
|
319
592
|
end
|
320
|
-
end
|
321
593
|
|
322
|
-
|
323
|
-
spec
|
324
|
-
|
325
|
-
|
326
|
-
|
594
|
+
+ topic('#report_environment()') do
|
595
|
+
- spec("[!rx7nn] prints ruby version, platform, several options, and so on.") do
|
596
|
+
bm = Benchmarker::Benchmark.new(title: "string concat", loop: 1000, inverse: true)
|
597
|
+
sout, serr = capture_sio { bm.__send__(:report_environment) }
|
598
|
+
ok {serr} == ""
|
599
|
+
ok {sout} =~ /^## title: +string concat$/
|
600
|
+
ok {sout} =~ /^## options: +loop=1000, iter=1, extra=0, inverse=true$/
|
601
|
+
ok {sout} =~ /^## benchmarker: +release \d+\.\d+\.\d+$/
|
602
|
+
ok {sout} =~ /^## ruby engine: +\w+ \(engine version .*\)$/
|
603
|
+
ok {sout} =~ /^## ruby platform: +.+$/
|
604
|
+
ok {sout} =~ /^## ruby path: +.+$/
|
605
|
+
ok {sout} =~ /^## compiler: +.*$/
|
606
|
+
ok {sout} =~ /^## cpu model: +.+$/
|
607
|
+
end
|
327
608
|
end
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
609
|
+
|
610
|
+
fixture :bm5 do
|
611
|
+
bm = Benchmarker::Benchmark.new(iter: 5, extra: 2).scope do
|
612
|
+
task "foo" do nil end
|
613
|
+
task "bar" do nil end
|
614
|
+
end
|
615
|
+
entries = bm.instance_eval{@entries}
|
616
|
+
#ok {entries[0][1]}.is_a?(Benchmarker::Result)
|
617
|
+
#ok {entries[1][1]}.is_a?(Benchmarker::Result)
|
618
|
+
#
|
619
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.1, 2.1, 3.1, 4.3))
|
620
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.2, 2.2, 3.2, 4.1))
|
621
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.3, 2.3, 3.3, 4.4))
|
622
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.4, 2.4, 3.4, 4.5))
|
623
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.5, 2.5, 3.5, 4.9))
|
624
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.6, 2.6, 3.6, 4.2))
|
625
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.7, 2.7, 3.7, 4.6))
|
626
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.8, 2.8, 3.8, 4.8))
|
627
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.9, 2.9, 3.9, 4.7))
|
628
|
+
#
|
629
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.1, 2.1, 3.1, 4.3))
|
630
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.2, 2.2, 3.2, 4.1))
|
631
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.3, 2.3, 3.3, 4.4))
|
632
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.4, 2.4, 3.4, 4.5))
|
633
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.5, 2.5, 3.5, 4.9))
|
634
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.6, 2.6, 3.6, 4.2))
|
635
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.7, 2.7, 3.7, 4.6))
|
636
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.8, 2.8, 3.8, 4.8))
|
637
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.9, 2.9, 3.9, 4.7))
|
638
|
+
#
|
639
|
+
bm
|
332
640
|
end
|
333
|
-
end
|
334
641
|
|
335
|
-
|
642
|
+
+ topic('#_removed_minmax()') do
|
643
|
+
- spec("[!uxe7e] removes best and worst results if 'extra' option specified.") do |bm5|
|
644
|
+
bm5.__send__(:_remove_minmax)
|
645
|
+
arr = bm5.instance_eval{@entries}.collect {|task, r|
|
646
|
+
real_list = []
|
647
|
+
r.each {|t| real_list << t.real }
|
648
|
+
[task.name, real_list]
|
649
|
+
}
|
650
|
+
ok {arr} == [
|
651
|
+
["foo", [4.30, 4.40, 4.50, 4.60, 4.70]],
|
652
|
+
["bar", [4.30, 4.40, 4.50, 4.60, 4.70]],
|
653
|
+
]
|
654
|
+
end
|
655
|
+
- spec("[!is6ll] returns removed min and max data.") do |bm5|
|
656
|
+
rows = bm5.__send__(:_remove_minmax)
|
657
|
+
ok {rows} == [
|
658
|
+
["foo", 4.10, "(#2)", 4.90, "(#5)"],
|
659
|
+
[nil , 4.20, "(#6)", 4.80, "(#8)"],
|
660
|
+
["bar", 4.10, "(#2)", 4.90, "(#5)"],
|
661
|
+
[nil , 4.20, "(#6)", 4.80, "(#8)"],
|
662
|
+
]
|
663
|
+
end
|
664
|
+
- spec("[!xwddz] sets removed best and worst results into JSON data.") do |bm5|
|
665
|
+
bm5.__send__(:_remove_minmax)
|
666
|
+
ok {bm5.instance_eval{@jdata}} == {
|
667
|
+
:RemovedMinMax => [
|
668
|
+
["foo", 4.10, "(#2)", 4.90, "(#5)"],
|
669
|
+
[nil , 4.20, "(#6)", 4.80, "(#8)"],
|
670
|
+
["bar", 4.10, "(#2)", 4.90, "(#5)"],
|
671
|
+
[nil , 4.20, "(#6)", 4.80, "(#8)"],
|
672
|
+
]
|
673
|
+
}
|
674
|
+
end
|
675
|
+
end
|
336
676
|
|
677
|
+
+ topic('#_render_minmax()') do
|
678
|
+
- spec("[!p71ax] returns rendered string.") do |bm5|
|
679
|
+
rows = bm5.__send__(:_remove_minmax)
|
680
|
+
str = bm5.__send__(:_render_minmax, rows)
|
681
|
+
ok {str} == <<"END"
|
337
682
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
@task1.real = 2.25
|
347
|
-
@task2 = Benchmarker::TASK.new("label1")
|
348
|
-
@task2.user = 1.125
|
349
|
-
@task2.sys = 0.25
|
350
|
-
@task2.total = 1.375
|
351
|
-
@task2.real = 1.5
|
352
|
-
end
|
683
|
+
## Removed Min & Max min iter max iter
|
684
|
+
foo \e[0;36m 4.1000\e[0m \e[0;35m (#2)\e[0m \e[0;36m 4.9000\e[0m \e[0;35m (#5)\e[0m
|
685
|
+
\e[0;36m 4.2000\e[0m \e[0;35m (#6)\e[0m \e[0;36m 4.8000\e[0m \e[0;35m (#8)\e[0m
|
686
|
+
bar \e[0;36m 4.1000\e[0m \e[0;35m (#2)\e[0m \e[0;36m 4.9000\e[0m \e[0;35m (#5)\e[0m
|
687
|
+
\e[0;36m 4.2000\e[0m \e[0;35m (#6)\e[0m \e[0;36m 4.8000\e[0m \e[0;35m (#8)\e[0m
|
688
|
+
END
|
689
|
+
end
|
690
|
+
end
|
353
691
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
692
|
+
+ topic('#_calc_average()') do
|
693
|
+
- spec("[!qu29s] calculates average of real times for each task.") do |bm5|
|
694
|
+
rows = bm5.__send__(:_calc_average)
|
695
|
+
ok {rows} == [
|
696
|
+
["foo", 1.50, 2.50, 3.50, 4.50],
|
697
|
+
["bar", 1.50, 2.50, 3.50, 4.50],
|
698
|
+
]
|
699
|
+
end
|
700
|
+
- spec("[!jxf28] sets average results into JSON data.") do |bm5|
|
701
|
+
bm5.__send__(:_calc_average)
|
702
|
+
ok {bm5.instance_eval{@jdata}} == {
|
703
|
+
:Average => [
|
704
|
+
["foo", 1.50, 2.50, 3.50, 4.50],
|
705
|
+
["bar", 1.50, 2.50, 3.50, 4.50],
|
706
|
+
]
|
707
|
+
}
|
708
|
+
end
|
360
709
|
end
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
710
|
+
|
711
|
+
+ topic('#_render_average()') do
|
712
|
+
- spec("[!j9wlv] returns rendered string.") do |bm5|
|
713
|
+
rows = bm5.__send__(:_calc_average)
|
714
|
+
str = bm5.__send__(:_render_average, rows)
|
715
|
+
ok {str} == <<"END"
|
716
|
+
|
717
|
+
## Average of 5 (=9-2*2) user sys total real
|
718
|
+
foo 1.5000 2.5000 3.5000 \e[0;36m 4.5000\e[0m
|
719
|
+
bar 1.5000 2.5000 3.5000 \e[0;36m 4.5000\e[0m
|
720
|
+
END
|
721
|
+
end
|
366
722
|
end
|
367
|
-
end
|
368
723
|
|
369
|
-
|
370
|
-
spec
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
724
|
+
+ topic('#report_stats()') do
|
725
|
+
- spec("[!0jn7d] sorts results by real sec.") do
|
726
|
+
bm = Benchmarker::Benchmark.new().scope do
|
727
|
+
task "foo" do nil end
|
728
|
+
task "bar" do nil end
|
729
|
+
task "baz" do nil end
|
730
|
+
end
|
731
|
+
entries = bm.instance_eval{@entries}
|
732
|
+
entries[0][1].add(Benchmarker::TimeSet.new(1.1, 2.1, 3.2, 4.3))
|
733
|
+
entries[1][1].add(Benchmarker::TimeSet.new(1.1, 2.1, 3.2, 3.3))
|
734
|
+
entries[2][1].add(Benchmarker::TimeSet.new(1.1, 2.1, 3.2, 5.3))
|
735
|
+
#
|
736
|
+
sout, serr = capture_sio { bm.__send__(:report_stats) }
|
737
|
+
ok {sout} == <<'END'
|
738
|
+
|
739
|
+
## Ranking real
|
740
|
+
bar 3.3000 (100.0%) ********************
|
741
|
+
foo 4.3000 ( 76.7%) ***************
|
742
|
+
baz 5.3000 ( 62.3%) ************
|
743
|
+
|
744
|
+
## Matrix real [1] [2] [3]
|
745
|
+
[1] bar 3.3000 100.0% 130.3% 160.6%
|
746
|
+
[2] foo 4.3000 76.7% 100.0% 123.3%
|
747
|
+
[3] baz 5.3000 62.3% 81.1% 100.0%
|
748
|
+
END
|
749
|
+
end
|
389
750
|
end
|
390
|
-
end
|
391
751
|
|
392
|
-
|
393
|
-
|
394
|
-
|
752
|
+
fixture :pairs do
|
753
|
+
[
|
754
|
+
["foo", 1.11],
|
755
|
+
["bar", 2.22],
|
756
|
+
["baz", 3.33],
|
757
|
+
]
|
395
758
|
end
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
759
|
+
|
760
|
+
+ topic('#_render_ranking()') do
|
761
|
+
- spec("[!2lu55] calculates ranking data and sets it into JSON data.") do |bm, pairs|
|
762
|
+
bm.__send__(:_render_ranking, pairs)
|
763
|
+
ok {bm.instance_eval{@jdata}} == {
|
764
|
+
:Ranking => [
|
765
|
+
["foo", 1.11, "100.0%", "0.90 times/sec", "********************"],
|
766
|
+
["bar", 2.22, "50.0%", "0.45 times/sec", "**********" ],
|
767
|
+
["baz", 3.33, "33.3%", "0.30 times/sec", "*******" ],
|
768
|
+
]
|
769
|
+
}
|
770
|
+
end
|
771
|
+
- spec("[!55x8r] returns rendered string of ranking.") do |bm, pairs|
|
772
|
+
str = bm.__send__(:_render_ranking, pairs)
|
773
|
+
ok {str} == <<"END"
|
774
|
+
|
775
|
+
## Ranking real
|
776
|
+
foo \e[0;36m 1.1100\e[0m (100.0%) ********************
|
777
|
+
bar \e[0;36m 2.2200\e[0m ( 50.0%) **********
|
778
|
+
baz \e[0;36m 3.3300\e[0m ( 33.3%) *******
|
779
|
+
END
|
780
|
+
end
|
401
781
|
end
|
402
|
-
end
|
403
782
|
|
404
|
-
|
405
|
-
spec
|
406
|
-
|
783
|
+
+ topic('#_render_matrix()') do
|
784
|
+
- spec("[!2lu55] calculates ranking data and sets it into JSON data.") do |bm, pairs|
|
785
|
+
bm.__send__(:_render_matrix, pairs)
|
786
|
+
ok {bm.instance_eval{@jdata}} == {
|
787
|
+
:Matrix => [
|
788
|
+
["[1] foo", 1.11, "100.0%", "200.0%", "300.0%"],
|
789
|
+
["[2] bar", 2.22, "50.0%", "100.0%", "150.0%"],
|
790
|
+
["[3] baz", 3.33, "33.3%", "66.7%", "100.0%"],
|
791
|
+
]
|
792
|
+
}
|
793
|
+
end
|
794
|
+
- spec("[!rwfxu] returns rendered string of matrix.") do |bm, pairs|
|
795
|
+
str = bm.__send__(:_render_matrix, pairs)
|
796
|
+
ok {str} == <<"END"
|
797
|
+
|
798
|
+
## Matrix real [1] [2] [3]
|
799
|
+
[1] foo \e[0;36m 1.1100\e[0m 100.0% 200.0% 300.0%
|
800
|
+
[2] bar \e[0;36m 2.2200\e[0m 50.0% 100.0% 150.0%
|
801
|
+
[3] baz \e[0;36m 3.3300\e[0m 33.3% 66.7% 100.0%
|
802
|
+
END
|
803
|
+
end
|
407
804
|
end
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
805
|
+
|
806
|
+
+ topic('#write_outfile()') do
|
807
|
+
- spec("[!o8ah6] writes result data into JSON file if 'outfile' option specified.") do
|
808
|
+
tmpfile = "tmp#{rand().to_s[2..6]}.json"
|
809
|
+
at_end { File.unlink tmpfile if File.exist?(tmpfile) }
|
810
|
+
jdata = {
|
811
|
+
:Ranking => [
|
812
|
+
["foo", 1.11, "100.0%", "0.90 times/sec", "********************"],
|
813
|
+
["bar", 2.22, "50.0%", "0.45 times/sec", "**********" ],
|
814
|
+
["baz", 3.33, "33.3%", "0.30 times/sec", "*******" ],
|
815
|
+
],
|
816
|
+
:Matrix => [
|
817
|
+
["[1] foo", 1.11, "100.0%", "200.0%", "300.0%"],
|
818
|
+
["[2] bar", 2.22, "50.0%", "100.0%", "150.0%"],
|
819
|
+
["[3] baz", 3.33, "33.3%", "66.7%", "100.0%"],
|
820
|
+
],
|
821
|
+
}
|
822
|
+
#
|
823
|
+
bm1 = Benchmarker::Benchmark.new()
|
824
|
+
bm1.instance_eval { @jdata = jdata }
|
825
|
+
bm1.__send__(:write_outfile)
|
826
|
+
ok {tmpfile}.NOT.file_exist?
|
827
|
+
#
|
828
|
+
bm2 = Benchmarker::Benchmark.new(outfile: tmpfile)
|
829
|
+
bm2.instance_eval { @jdata = jdata }
|
830
|
+
bm2.__send__(:write_outfile)
|
831
|
+
ok {tmpfile}.file_exist?
|
832
|
+
actual = JSON.load(File.read(tmpfile))
|
833
|
+
ok {actual} == {"Ranking"=>jdata[:Ranking], "Matrix"=>jdata[:Matrix]}
|
834
|
+
end
|
413
835
|
end
|
836
|
+
|
837
|
+
+ topic('#colorize?') do
|
838
|
+
- spec("[!cy10n] returns true if '-c' option specified.") do
|
839
|
+
bm = Benchmarker.new(colorize: true)
|
840
|
+
ok {bm.__send__(:colorize?)} == true
|
841
|
+
capture_sio do
|
842
|
+
ok {bm.__send__(:colorize?)} == true
|
843
|
+
end
|
844
|
+
end
|
845
|
+
- spec("[!e0gcz] returns false if '-C' option specified.") do
|
846
|
+
bm = Benchmarker.new(colorize: false)
|
847
|
+
ok {bm.__send__(:colorize?)} == false
|
848
|
+
capture_sio do
|
849
|
+
ok {bm.__send__(:colorize?)} == false
|
850
|
+
end
|
851
|
+
end
|
852
|
+
- spec("[!6v90d] returns result of `Color.colorize?` if neither '-c' nor '-C' specified.") do
|
853
|
+
bm = Benchmarker.new()
|
854
|
+
ok {bm.__send__(:colorize?)} == true
|
855
|
+
capture_sio do
|
856
|
+
ok {bm.__send__(:colorize?)} == false
|
857
|
+
end
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
414
861
|
end
|
415
862
|
|
416
|
-
|
417
|
-
|
418
|
-
|
863
|
+
|
864
|
+
+ topic(Benchmarker::Scope) do
|
865
|
+
|
866
|
+
fixture :bm do
|
867
|
+
Benchmarker::Benchmark.new()
|
419
868
|
end
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
ok {@task1.total} == 4.0
|
424
|
-
ok {@task1.real } == 4.5
|
869
|
+
|
870
|
+
fixture :scope do |bm|
|
871
|
+
Benchmarker::Scope.new(bm)
|
425
872
|
end
|
426
|
-
end
|
427
873
|
|
428
|
-
|
429
|
-
spec
|
430
|
-
|
874
|
+
+ topic('#task()') do
|
875
|
+
- spec("[!j6pmr] creates new task object.") do |scope|
|
876
|
+
task = scope.task "name1", tag: "abc" do end
|
877
|
+
ok {task}.is_a?(Benchmarker::Task)
|
878
|
+
ok {task.name} == "name1"
|
879
|
+
ok {task.tag} == "abc"
|
880
|
+
end
|
881
|
+
- spec("[!kh7r9] define empty-loop task if name is nil.") do |scope|
|
882
|
+
task = scope.task nil do end
|
883
|
+
ok {task}.is_a?(Benchmarker::Task)
|
884
|
+
ok {task.name} == nil
|
885
|
+
end
|
886
|
+
+ case_when("[!843ju] when code argument provided...") do
|
887
|
+
- spec("[!bwfak] code argument and block argument are exclusive.") do |scope|
|
888
|
+
pr = proc { scope.task "foo", "x = 1+1" do nil end }
|
889
|
+
ok {pr}.raise?(Benchmarker::TaskError, "task(\"foo\"): cannot accept String argument when block argument given.")
|
890
|
+
end
|
891
|
+
- spec("[!4dm9q] generates block argument if code argument passed.") do |scope|
|
892
|
+
x = 0
|
893
|
+
task = scope.task "foo", "x += 1", binding()
|
894
|
+
ok {task.instance_eval{@block}}.is_a?(Proc)
|
895
|
+
task.instance_eval{@block}.call()
|
896
|
+
ok {x} == 100
|
897
|
+
end
|
898
|
+
end
|
431
899
|
end
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
900
|
+
|
901
|
+
+ topic('#empty_task()') do
|
902
|
+
- spec("[!ycoch] creates new empty-loop task object.") do |scope|
|
903
|
+
task = scope.empty_task do end
|
904
|
+
ok {task}.is_a?(Benchmarker::Task)
|
905
|
+
ok {task.name} == nil
|
906
|
+
end
|
437
907
|
end
|
438
|
-
end
|
439
908
|
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
t = klass.average([@task1, @task2])
|
449
|
-
ok {t.label} == @task1.label
|
450
|
-
not_ok {t.label}.same?(@task1)
|
451
|
-
end
|
452
|
-
spec "returns averaged task." do
|
453
|
-
t = klass.average([@task1, @task2, @task1, @task2])
|
454
|
-
ok {t.user } == (@task1.user + @task2.user ) / 2
|
455
|
-
ok {t.sys } == (@task1.sys + @task2.sys ) / 2
|
456
|
-
ok {t.total} == (@task1.total + @task2.total) / 2
|
457
|
-
ok {t.real } == (@task1.real + @task2.real ) / 2
|
909
|
+
+ topic('#before()') do
|
910
|
+
- spec("[!2ir4q] defines 'before' hook.") do |scope, bm|
|
911
|
+
called = false
|
912
|
+
scope.before do called = true end
|
913
|
+
ok {called} == false
|
914
|
+
bm.__send__(:call_hook, :before)
|
915
|
+
ok {called} == true
|
916
|
+
end
|
458
917
|
end
|
459
|
-
end
|
460
918
|
|
461
|
-
|
919
|
+
+ topic('#after()') do
|
920
|
+
- spec("[!05up6] defines 'after' hook.") do |scope, bm|
|
921
|
+
called = false
|
922
|
+
scope.after do called = true end
|
923
|
+
ok {called} == false
|
924
|
+
bm.__send__(:call_hook, :after)
|
925
|
+
ok {called} == true
|
926
|
+
end
|
927
|
+
end
|
462
928
|
|
929
|
+
+ topic('#before_all()') do
|
930
|
+
- spec("[!1oier] defines 'before_all' hook.") do |scope, bm|
|
931
|
+
called = false
|
932
|
+
scope.before_all do called = true end
|
933
|
+
ok {called} == false
|
934
|
+
bm.__send__(:call_hook, :before_all)
|
935
|
+
ok {called} == true
|
936
|
+
end
|
937
|
+
end
|
463
938
|
|
464
|
-
|
465
|
-
|
939
|
+
+ topic('#after_all()') do
|
940
|
+
- spec("[!z7xop] defines 'after_all' hook.") do |scope, bm|
|
941
|
+
called = false
|
942
|
+
scope.after_all do called = true end
|
943
|
+
ok {called} == false
|
944
|
+
bm.__send__(:call_hook, :after_all)
|
945
|
+
ok {called} == true
|
946
|
+
end
|
947
|
+
end
|
466
948
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
949
|
+
+ topic('#validate()') do
|
950
|
+
- spec("[!q2aev] defines validator.") do
|
951
|
+
bm = Benchmarker::Benchmark.new()
|
952
|
+
scope = Benchmarker::Scope.new(bm)
|
953
|
+
ok {bm.instance_eval{@hooks[:validate]}} == nil
|
954
|
+
scope.validate do |ret| end
|
955
|
+
ok {bm.instance_eval{@hooks[:validate]}} != nil
|
956
|
+
ok {bm.instance_eval{@hooks[:validate]}}.is_a?(Proc)
|
957
|
+
end
|
958
|
+
end
|
471
959
|
|
472
|
-
|
473
|
-
spec
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
960
|
+
+ topic('#assert()') do
|
961
|
+
- spec("[!a0c7e] do nothing if assertion succeeded.") do |scope|
|
962
|
+
capture_sio do
|
963
|
+
pr = proc { scope.assert 1+1 == 2, "1+1 is 2" }
|
964
|
+
ok {pr}.NOT.raise?
|
965
|
+
end
|
966
|
+
end
|
967
|
+
- spec("[!5vmbc] raises error if assertion failed.") do |scope|
|
968
|
+
capture_sio do
|
969
|
+
pr = proc { scope.assert 1+1 == 1, "1+1 is not 1" }
|
970
|
+
ok {pr}.raise?(Benchmarker::ValidationFailed, "1+1 is not 1")
|
971
|
+
end
|
972
|
+
end
|
973
|
+
- spec("[!7vt5l] puts newline if assertion failed.") do |scope|
|
974
|
+
sout, serr = capture_sio do
|
975
|
+
pr = proc { scope.assert true, "" }
|
976
|
+
ok {pr}.NOT.raise?(Benchmarker::ValidationFailed)
|
977
|
+
end
|
978
|
+
ok {sout} == ""
|
979
|
+
#
|
980
|
+
sout, serr = capture_sio do
|
981
|
+
pr = proc { scope.assert false, "" }
|
982
|
+
ok {pr}.raise?(Benchmarker::ValidationFailed)
|
983
|
+
end
|
984
|
+
ok {sout} == "\n"
|
985
|
+
end
|
986
|
+
- spec("[!mhw59] makes error backtrace compact.") do |scope|
|
987
|
+
capture_sio do
|
988
|
+
pr = proc { scope.assert false, "" }
|
989
|
+
ok {pr}.raise?(Benchmarker::ValidationFailed) do |exc|
|
990
|
+
ok {exc.backtrace}.all? {|x| x !~ /benchmarker\.rb/ }
|
991
|
+
end
|
992
|
+
end
|
993
|
+
end
|
479
994
|
end
|
480
|
-
end
|
481
995
|
|
482
|
-
|
483
|
-
spec
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
996
|
+
+ topic('#assert_eq()') do
|
997
|
+
- spec("[!8m6bh] do nothing if ectual == expected.") do |scope|
|
998
|
+
capture_sio do
|
999
|
+
pr = proc { scope.assert_eq 1+1, 2 }
|
1000
|
+
ok {pr}.NOT.raise?
|
1001
|
+
end
|
1002
|
+
end
|
1003
|
+
- spec("[!f9ey6] raises error unless actual == expected.") do |scope|
|
1004
|
+
capture_sio do
|
1005
|
+
pr = proc { scope.assert_eq 'a'*3, 'aa' }
|
1006
|
+
ok {pr}.raise?(Benchmarker::ValidationFailed, '"aaa" == "aa": failed.')
|
489
1007
|
end
|
490
|
-
r.write("Kyon\n")
|
491
1008
|
end
|
492
|
-
ok {sout} == "Haruhi\nKyon\n"
|
493
|
-
ok {serr} == "Sasaki\n"
|
494
1009
|
end
|
1010
|
+
|
495
1011
|
end
|
496
1012
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
1013
|
+
|
1014
|
+
+ topic(Benchmarker::Task) do
|
1015
|
+
|
1016
|
+
+ topic('#invoke()') do
|
1017
|
+
+ case_when("[!s2f6v] when task block is build from repeated code...") do
|
1018
|
+
- spec("[!i2r8o] error when number of loop is less than 100.") do
|
1019
|
+
capture_sio do
|
1020
|
+
pr = proc do
|
1021
|
+
Benchmarker.scope(loop: 100) do
|
1022
|
+
task "foo", "x = 1+1"
|
1023
|
+
end
|
1024
|
+
end
|
1025
|
+
ok {pr}.NOT.raise?
|
1026
|
+
#
|
1027
|
+
pr = proc do
|
1028
|
+
Benchmarker.scope(loop: 99) do
|
1029
|
+
task "foo", "x = 1+1"
|
1030
|
+
end
|
1031
|
+
end
|
1032
|
+
ok {pr}.raise?(Benchmarker::TaskError, 'task("foo"): number of loop (=99) should be >= 100, but not.')
|
1033
|
+
end
|
1034
|
+
end
|
1035
|
+
- spec("[!kzno6] error when number of loop is not a multiple of 100.") do
|
1036
|
+
capture_sio do
|
1037
|
+
pr = proc do
|
1038
|
+
Benchmarker.scope(loop: 200) do
|
1039
|
+
task "foo", "x = 1+1"
|
1040
|
+
end
|
1041
|
+
end
|
1042
|
+
ok {pr}.NOT.raise?
|
1043
|
+
#
|
1044
|
+
pr = proc do
|
1045
|
+
Benchmarker.scope(loop: 250) do
|
1046
|
+
task "foo", "x = 1+1"
|
1047
|
+
end
|
1048
|
+
end
|
1049
|
+
ok {pr}.raise?(Benchmarker::TaskError, 'task("foo"): number of loop (=250) should be a multiple of 100, but not.')
|
1050
|
+
end
|
1051
|
+
end
|
1052
|
+
- spec("[!gbukv] changes number of loop to 1/100.") do
|
1053
|
+
capture_sio do
|
1054
|
+
called = 0
|
1055
|
+
Benchmarker.scope(loop: 200) do
|
1056
|
+
task "foo", "called +=1", binding()
|
1057
|
+
end
|
1058
|
+
ok {called} == 200
|
1059
|
+
end
|
1060
|
+
end
|
1061
|
+
end
|
1062
|
+
- spec("[!frq25] kicks GC before calling task block.") do
|
1063
|
+
capture_sio do
|
1064
|
+
rec = recorder()
|
1065
|
+
rec.record_method(GC, :start)
|
1066
|
+
called = false
|
1067
|
+
Benchmarker.scope() do
|
1068
|
+
task "foo" do called = true end
|
1069
|
+
end
|
1070
|
+
ok {called} == true
|
1071
|
+
ok {rec[0].obj} == GC
|
1072
|
+
ok {rec[0].name} == :start
|
1073
|
+
end
|
1074
|
+
end
|
1075
|
+
- spec("[!tgql6] invokes block N times.") do
|
1076
|
+
cnt = 0
|
1077
|
+
task = Benchmarker::Task.new("name1") do cnt += 1 end
|
1078
|
+
task.invoke(3)
|
1079
|
+
ok {cnt} == 3
|
1080
|
+
end
|
1081
|
+
- spec("[!9e5pr] returns TimeSet object.") do
|
1082
|
+
task = Benchmarker::Task.new("name1") do nil end
|
1083
|
+
ret = task.invoke()
|
1084
|
+
ok {ret}.is_a?(Benchmarker::TimeSet)
|
1085
|
+
end
|
1086
|
+
- spec("[!zw4kt] yields validator with result value of block.") do
|
1087
|
+
task = Benchmarker::Task.new("name1", tag: "curr") do 234 end
|
1088
|
+
args = nil
|
1089
|
+
task.invoke() do |*a| args = a end
|
1090
|
+
ok {args} == [234, "name1", "curr"]
|
1091
|
+
end
|
504
1092
|
end
|
1093
|
+
|
505
1094
|
end
|
506
1095
|
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
1096
|
+
|
1097
|
+
+ topic(Benchmarker::TimeSet) do
|
1098
|
+
|
1099
|
+
+ topic('#-()') do
|
1100
|
+
- spec("[!cpwgf] returns new TimeSet object.") do
|
1101
|
+
t1 = Benchmarker::TimeSet.new(2.0, 3.0, 4.0, 5.0)
|
1102
|
+
t2 = Benchmarker::TimeSet.new(2.5, 3.5, 5.0, 5.25)
|
1103
|
+
t3 = t2 - t1
|
1104
|
+
ok {t3} != t1
|
1105
|
+
ok {t3} != t2
|
1106
|
+
ok {t3.user} == 0.5
|
1107
|
+
ok {t3.sys} == 0.5
|
1108
|
+
ok {t3.total} == 1.0
|
1109
|
+
ok {t3.real} == 0.25
|
1110
|
+
end
|
511
1111
|
end
|
512
|
-
|
513
|
-
|
1112
|
+
|
1113
|
+
+ topic('#div()') do
|
1114
|
+
- spec("[!4o9ns] returns new TimeSet object which values are divided by n.") do
|
1115
|
+
t1 = Benchmarker::TimeSet.new(2.5, 3.5, 5.0, 5.25)
|
1116
|
+
t2 = t1.div(100)
|
1117
|
+
ok {t2.user } == 0.025
|
1118
|
+
ok {t2.sys } == 0.035
|
1119
|
+
ok {t2.total} == 0.050
|
1120
|
+
ok {t2.real } == 0.0525
|
1121
|
+
end
|
514
1122
|
end
|
1123
|
+
|
515
1124
|
end
|
516
1125
|
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
1126
|
+
|
1127
|
+
+ topic(Benchmarker::Result) do
|
1128
|
+
|
1129
|
+
fixture :r do
|
1130
|
+
Benchmarker::Result.new
|
521
1131
|
end
|
522
|
-
|
523
|
-
|
1132
|
+
|
1133
|
+
+ topic('#add()') do
|
1134
|
+
- spec("[!thyms] adds timeset and returns self.") do |r|
|
1135
|
+
t = Benchmarker::TimeSet.new(1.0, 2.0, 3.0, 4.0)
|
1136
|
+
r.add(t)
|
1137
|
+
ok {r[0]} == t
|
1138
|
+
end
|
524
1139
|
end
|
525
|
-
|
526
|
-
|
1140
|
+
|
1141
|
+
+ topic('#clear()') do
|
1142
|
+
- spec("[!fxrn6] clears timeset array.") do |r|
|
1143
|
+
ok {r.length} == 0
|
1144
|
+
r.add(Benchmarker::TimeSet.new(1.0, 2.0, 3.0, 4.0))
|
1145
|
+
r.add(Benchmarker::TimeSet.new(0.0, 0.0, 0.0, 0.0))
|
1146
|
+
ok {r.length} == 2
|
1147
|
+
r.clear()
|
1148
|
+
ok {r.length} == 0
|
1149
|
+
end
|
527
1150
|
end
|
528
|
-
end
|
529
1151
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
1152
|
+
+ topic('#skipped?') do
|
1153
|
+
- spec("[!bvzk9] returns true if reason has set, or returns false.") do |r|
|
1154
|
+
ok {r.skipped?} == false
|
1155
|
+
r.skipped = "why skipped"
|
1156
|
+
ok {r.skipped?} == true
|
1157
|
+
end
|
534
1158
|
end
|
535
|
-
|
536
|
-
|
1159
|
+
|
1160
|
+
+ topic('#remove_minmax()') do
|
1161
|
+
- spec("[!b55zh] removes best and worst timeset and returns them.") do |r|
|
1162
|
+
klass = Benchmarker::TimeSet
|
1163
|
+
arr = [
|
1164
|
+
klass.new(0.1, 0.1, 0.1, 0.3),
|
1165
|
+
klass.new(0.1, 0.1, 0.1, 0.1),
|
1166
|
+
klass.new(0.1, 0.1, 0.1, 0.4),
|
1167
|
+
klass.new(0.1, 0.1, 0.1, 0.5),
|
1168
|
+
klass.new(0.1, 0.1, 0.1, 0.9),
|
1169
|
+
klass.new(0.1, 0.1, 0.1, 0.2),
|
1170
|
+
klass.new(0.1, 0.1, 0.1, 0.6),
|
1171
|
+
klass.new(0.1, 0.1, 0.1, 0.8),
|
1172
|
+
klass.new(0.1, 0.1, 0.1, 0.7),
|
1173
|
+
]
|
1174
|
+
#
|
1175
|
+
r1 = Benchmarker::Result.new
|
1176
|
+
arr.each {|t| r1.add(t) }
|
1177
|
+
removed = r1.remove_minmax(1)
|
1178
|
+
ok {removed} == [
|
1179
|
+
[0.1, 2, 0.9, 5],
|
1180
|
+
]
|
1181
|
+
vals = []; r1.each {|t| vals << t.real }
|
1182
|
+
ok {vals} == [0.3, 0.4, 0.5, 0.2, 0.6, 0.8, 0.7]
|
1183
|
+
#
|
1184
|
+
r2 = Benchmarker::Result.new
|
1185
|
+
arr.each {|t| r2.add(t) }
|
1186
|
+
removed = r2.remove_minmax(2)
|
1187
|
+
ok {removed} == [
|
1188
|
+
[0.1, 2, 0.9, 5],
|
1189
|
+
[0.2, 6, 0.8, 8],
|
1190
|
+
]
|
1191
|
+
vals = []; r2.each {|t| vals << t.real }
|
1192
|
+
ok {vals} == [0.3, 0.4, 0.5, 0.6, 0.7]
|
1193
|
+
end
|
537
1194
|
end
|
538
|
-
|
539
|
-
|
1195
|
+
|
1196
|
+
+ topic('#calc_average()') do
|
1197
|
+
- spec("[!b91w3] returns average of timeddata.") do |r|
|
1198
|
+
klass = Benchmarker::TimeSet
|
1199
|
+
arr = [
|
1200
|
+
klass.new(0.1, 0.1, 0.3, 0.3),
|
1201
|
+
klass.new(0.2, 0.1, 0.3, 0.1),
|
1202
|
+
klass.new(0.3, 0.1, 0.3, 0.4),
|
1203
|
+
klass.new(0.4, 0.1, 0.3, 0.5),
|
1204
|
+
klass.new(0.5, 0.1, 0.3, 0.9),
|
1205
|
+
klass.new(0.6, 0.1, 0.3, 0.2),
|
1206
|
+
klass.new(0.7, 0.1, 0.3, 0.6),
|
1207
|
+
klass.new(0.8, 0.1, 0.3, 0.8),
|
1208
|
+
klass.new(0.9, 0.1, 0.3, 0.7),
|
1209
|
+
]
|
1210
|
+
arr.each {|t| r.add(t) }
|
1211
|
+
t = r.calc_average()
|
1212
|
+
ok {t}.is_a?(klass)
|
1213
|
+
ok {t.user }.in_delta?(0.5, 0.000000001)
|
1214
|
+
ok {t.sys }.in_delta?(0.1, 0.000000001)
|
1215
|
+
ok {t.total}.in_delta?(0.3, 0.000000001)
|
1216
|
+
ok {t.real }.in_delta?(0.5, 0.000000001)
|
1217
|
+
end
|
1218
|
+
|
540
1219
|
end
|
1220
|
+
|
541
1221
|
end
|
542
1222
|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
ok {ret}.same?(@r)
|
1223
|
+
|
1224
|
+
+ topic(Benchmarker::Color) do
|
1225
|
+
|
1226
|
+
+ topic('.colorize?()') do
|
1227
|
+
- spec("[!fc741] returns true if stdout is a tty, else returns false.") do
|
1228
|
+
ok {Benchmarker::Color.colorize?} == true
|
1229
|
+
capture_sio do
|
1230
|
+
ok {Benchmarker::Color.colorize?} == false
|
1231
|
+
end
|
1232
|
+
end
|
554
1233
|
end
|
1234
|
+
|
555
1235
|
end
|
556
1236
|
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
1237
|
+
|
1238
|
+
+ topic(Benchmarker::Misc) do
|
1239
|
+
|
1240
|
+
+ topic('.environment_info()') do
|
1241
|
+
- spec("[!w1xfa] returns environment info in key-value list.") do
|
1242
|
+
arr = Benchmarker::Misc.environment_info()
|
1243
|
+
ok {arr}.is_a?(Array)
|
1244
|
+
ok {arr[0][0]} == "benchmarker"
|
1245
|
+
ok {arr[1][0]} == "ruby engine"
|
1246
|
+
ok {arr[2][0]} == "ruby version"
|
1247
|
+
ok {arr[3][0]} == "ruby platform"
|
1248
|
+
ok {arr[4][0]} == "ruby path"
|
1249
|
+
ok {arr[5][0]} == "compiler"
|
1250
|
+
ok {arr[6][0]} == "os name"
|
1251
|
+
ok {arr[7][0]} == "cpu model"
|
1252
|
+
ok {arr[8]} == nil
|
1253
|
+
end
|
568
1254
|
end
|
569
|
-
end
|
570
1255
|
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
@r.instance_variable_set('@format_label', "%-12s")
|
577
|
-
@r.report_task_label("Sasakisan")
|
578
|
-
ok {@buf} == "Sasakisan "
|
1256
|
+
+ topic('.os_name()') do
|
1257
|
+
- spec("[!83vww] returns string representing os name.") do
|
1258
|
+
str = Benchmarker::Misc.os_name()
|
1259
|
+
ok {str}.is_a?(String)
|
1260
|
+
end
|
579
1261
|
end
|
580
|
-
|
581
|
-
|
1262
|
+
|
1263
|
+
+ topic('.cpu_model()') do
|
1264
|
+
- spec("[!6ncgq] returns string representing cpu model.") do
|
1265
|
+
str = Benchmarker::Misc.cpu_model()
|
1266
|
+
ok {str}.is_a?(String)
|
1267
|
+
end
|
582
1268
|
end
|
1269
|
+
|
583
1270
|
end
|
584
1271
|
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
1272
|
+
|
1273
|
+
+ topic(Benchmarker::OptionParser) do
|
1274
|
+
|
1275
|
+
fixture :p do
|
1276
|
+
Benchmarker::OptionParser.new("hvq", "wnixoF", "I")
|
589
1277
|
end
|
590
|
-
|
591
|
-
|
1278
|
+
|
1279
|
+
+ topic('#parse()') do
|
1280
|
+
- spec("[!2gq7g] returns options and keyvals.")do |p|
|
1281
|
+
argv = ['-hqn100', '-i', '5', '-I', '--help', '--foo=bar']
|
1282
|
+
options, keyvals = p.parse(argv)
|
1283
|
+
ok {options} == {'h'=>true, 'q'=>true, 'n'=>'100', 'i'=>'5', 'I'=>true}
|
1284
|
+
ok {keyvals} == {'help'=>true, 'foo'=>'bar'}
|
1285
|
+
ok {argv} == []
|
1286
|
+
end
|
1287
|
+
- spec("[!ulfpu] stops parsing when '--' found.") do |p|
|
1288
|
+
argv = ['-h', '--', '-i', '5']
|
1289
|
+
options, keyvals = p.parse(argv)
|
1290
|
+
ok {options} == {'h'=>true}
|
1291
|
+
ok {keyvals} == {}
|
1292
|
+
ok {argv} == ['-i', '5']
|
1293
|
+
end
|
1294
|
+
- spec("[!8f085] regards '--long=option' as key-value.") do |p|
|
1295
|
+
argv = ['--foo=bar', '--baz']
|
1296
|
+
options, keyvals = p.parse(argv)
|
1297
|
+
ok {options} == {}
|
1298
|
+
ok {keyvals} == {'foo'=>'bar', 'baz'=>true}
|
1299
|
+
ok {argv} == []
|
1300
|
+
end
|
1301
|
+
- spec("[!dkq1u] parses short options.") do |p|
|
1302
|
+
argv = ['-h', '-qn100', '-vi', '10', '-x', '2']
|
1303
|
+
options, keyvals = p.parse(argv)
|
1304
|
+
ok {options} == {'h'=>true, 'q'=>true, 'n'=>'100', 'v'=>true, 'i'=>'10', 'x'=>'2'}
|
1305
|
+
ok {keyvals} == {}
|
1306
|
+
ok {argv} == []
|
1307
|
+
end
|
1308
|
+
- spec("[!8xqla] error when required argument is not provided.") do |p|
|
1309
|
+
argv = ['-qn']
|
1310
|
+
a_ = nil
|
1311
|
+
p.parse(argv) do |*a| a_ = a end
|
1312
|
+
ok {a_} == ["-n: argument required."]
|
1313
|
+
end
|
1314
|
+
- spec("[!tmx6o] error when option is unknown.") do |p|
|
1315
|
+
argv = ['-hz']
|
1316
|
+
a_ = nil
|
1317
|
+
p.parse(argv) do |*a| a_ = a end
|
1318
|
+
ok {a_} == ["-z: unknown option."]
|
1319
|
+
end
|
592
1320
|
end
|
593
|
-
end
|
594
1321
|
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
1322
|
+
+ topic('.parse_options()') do
|
1323
|
+
- spec("[!v19y5] converts option argument into integer if necessary.") do
|
1324
|
+
argv = ['-h', '-n100', '-vi', '10', '-x', '2', '-I5000']
|
1325
|
+
options, keyvals = Benchmarker::OptionParser.parse_options(argv)
|
1326
|
+
ok {options} == {"h"=>true, "n"=>100, "v"=>true, "i"=>10, "x"=>2, "I"=>5000}
|
1327
|
+
ok {keyvals} == {}
|
1328
|
+
end
|
1329
|
+
- spec("[!frfz2] yields error message when argument of '-n/i/x/I' is not an integer.") do
|
1330
|
+
err = nil
|
1331
|
+
Benchmarker::OptionParser.parse_options(['-nxx']) do |s| err = s end
|
1332
|
+
ok {err} == "-n xx: integer expected."
|
1333
|
+
#
|
1334
|
+
err = nil
|
1335
|
+
Benchmarker::OptionParser.parse_options(['-iyy']) do |s| err = s end
|
1336
|
+
ok {err} == "-i yy: integer expected."
|
1337
|
+
#
|
1338
|
+
err = nil
|
1339
|
+
Benchmarker::OptionParser.parse_options(['-xzz']) do |s| err = s end
|
1340
|
+
ok {err} == "-x zz: integer expected."
|
1341
|
+
#
|
1342
|
+
err = nil
|
1343
|
+
Benchmarker::OptionParser.parse_options(['-Izz']) do |s| err = s end
|
1344
|
+
ok {err} == "-Izz: integer expected."
|
1345
|
+
end
|
1346
|
+
- spec("[!nz15w] convers '-s' option value into number (integer or float).") do
|
1347
|
+
options, _ = Benchmarker::OptionParser.parse_options(['-s', '123'])
|
1348
|
+
ok {options} == {"s"=>123}
|
1349
|
+
options, _ = Benchmarker::OptionParser.parse_options(['-s', '0.5'])
|
1350
|
+
ok {options} == {"s"=>0.5}
|
1351
|
+
end
|
1352
|
+
- spec("[!3x1m7] yields error message when argument of '-s' is not a number.") do
|
1353
|
+
err = nil
|
1354
|
+
Benchmarker::OptionParser.parse_options(['-s', 'aa']) do |s| err = s end
|
1355
|
+
ok {err} == "-s aa: number expected."
|
1356
|
+
end
|
1357
|
+
- spec("[!emavm] yields error message when argumetn of '-F' option is invalid.") do
|
1358
|
+
err = nil
|
1359
|
+
Benchmarker::OptionParser.parse_options(['-F', 'xyz']) do |s| err = s end
|
1360
|
+
ok {err} == "-F xyz: invalid filter (expected operator is '=' or '!=')."
|
1361
|
+
#
|
1362
|
+
err = nil
|
1363
|
+
Benchmarker::OptionParser.parse_options(['-F', 'name=xyz']) do |s| err = s end
|
1364
|
+
ok {err} == "-F name=xyz: expected 'task=...' or 'tag=...'."
|
1365
|
+
end
|
599
1366
|
end
|
600
|
-
|
601
|
-
|
1367
|
+
|
1368
|
+
+ topic('.help_message()') do
|
1369
|
+
- spec("[!jnm2w] returns help message.") do
|
1370
|
+
msg = Benchmarker::OptionParser.help_message("bench.rb")
|
1371
|
+
ok {msg} == <<'END'
|
1372
|
+
Usage: bench.rb [<options>]
|
1373
|
+
-h, --help : help message
|
1374
|
+
-v : print Benchmarker version
|
1375
|
+
-w <N> : width of task name (default: 30)
|
1376
|
+
-n <N> : loop N times in each benchmark (default: 1)
|
1377
|
+
-i <N> : iterates all benchmark tasks N times (default: 1)
|
1378
|
+
-x <N> : ignore worst N results and best N results (default: 0)
|
1379
|
+
-I[<N>] : print inverse number (= N/sec) (default: same as '-n')
|
1380
|
+
-o <file> : output file in JSON format
|
1381
|
+
-q : quiet a little (suppress output of each iteration)
|
1382
|
+
-c : enable colorized output
|
1383
|
+
-C : disable colorized output
|
1384
|
+
-s <N> : sleep N seconds after each benchmark task
|
1385
|
+
-S : print sample code
|
1386
|
+
-F task=<...> : filter benchmark task by name (operator: '=' or '!=')
|
1387
|
+
-F tag=<...> : filter benchmark task by tag (operator: '=' or '!=')
|
1388
|
+
--<key>[=<val>]: define global variable `$opt_<key> = "<val>"`
|
1389
|
+
END
|
1390
|
+
end
|
602
1391
|
end
|
1392
|
+
|
603
1393
|
end
|
604
1394
|
|
605
|
-
end
|
606
1395
|
|
1396
|
+
+ topic(Benchmarker) do
|
607
1397
|
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
def before
|
612
|
-
@out = ""
|
613
|
-
@r = Benchmarker::Reporter.new(:out=>@out)
|
614
|
-
@stats = Benchmarker::Stats.new(@r)
|
615
|
-
#
|
616
|
-
@tasks = []
|
617
|
-
sos = proc do |label, user, sys, total, real|
|
618
|
-
t = Benchmarker::TASK.new(label)
|
619
|
-
t.user, t.sys, t.total, t.real = user, sys, total, real
|
620
|
-
@tasks << t
|
621
|
-
end
|
622
|
-
sos.call("Haruhi", 11.1, 0.2, 11.3, 11.5)
|
623
|
-
sos.call("Mikuru", 14.1, 0.2, 14.3, 14.5)
|
624
|
-
sos.call("Yuki", 10.1, 0.2, 10.3, 10.5)
|
625
|
-
sos.call("Itsuki", 12.1, 0.2, 12.3, 12.5)
|
626
|
-
sos.call("Kyon", 13.1, 0.2, 13.3, 13.5)
|
627
|
-
end
|
1398
|
+
after do
|
1399
|
+
Benchmarker::OPTIONS.clear()
|
1400
|
+
end
|
628
1401
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
1402
|
+
+ topic('.parse_cmdopts()') do
|
1403
|
+
- spec("[!348ip] parses command-line options.") do
|
1404
|
+
ok {Benchmarker::OPTIONS} == {}
|
1405
|
+
argv = "-q -n 1000 -i10 -x2 -I -o tmp.json".split()
|
1406
|
+
options, keyvals = Benchmarker.parse_cmdopts(argv)
|
1407
|
+
ok {options} == {'q'=>true, 'n'=>1000, 'i'=>10, 'x'=>2, 'I'=>true, 'o'=>"tmp.json"}
|
1408
|
+
ok {keyvals} == {}
|
1409
|
+
end
|
1410
|
+
- spec("[!snqxo] exits with status code 1 if error in command option.") do
|
1411
|
+
argv = ["-n abc"]
|
1412
|
+
sout, serr = capture_sio do
|
1413
|
+
pr = proc { Benchmarker.parse_cmdopts(argv) }
|
1414
|
+
ok {pr}.raise?(SystemExit) do |exc|
|
1415
|
+
ok {exc.status} == 1
|
1416
|
+
end
|
1417
|
+
end
|
1418
|
+
ok {serr} == "-n abc: integer expected.\n"
|
1419
|
+
ok {sout} == ""
|
1420
|
+
end
|
1421
|
+
- spec("[!p3b93] prints help message if '-h' or '--help' option specified.") do
|
1422
|
+
["-h", "--help"].each do |arg|
|
1423
|
+
sout, serr = capture_sio do
|
1424
|
+
pr = proc { Benchmarker.parse_cmdopts([arg]) }
|
1425
|
+
ok {pr}.raise?(SystemExit) do |exc|
|
1426
|
+
ok {exc.status} == 0
|
1427
|
+
end
|
1428
|
+
end
|
1429
|
+
ok {serr} == ""
|
1430
|
+
ok {sout} =~ /^Usage: \S+ \[<options>\]$/
|
1431
|
+
ok {sout} =~ /^ -h, --help : help message$/
|
1432
|
+
end
|
1433
|
+
end
|
1434
|
+
- spec("[!iaryj] prints version number if '-v' option specified.") do
|
1435
|
+
argv = ["-v"]
|
1436
|
+
sout, serr = capture_sio do
|
1437
|
+
pr = proc { Benchmarker.parse_cmdopts(argv) }
|
1438
|
+
ok {pr}.raise?(SystemExit) do |exc|
|
1439
|
+
ok {exc.status} == 0
|
1440
|
+
end
|
1441
|
+
end
|
1442
|
+
ok {serr} == ""
|
1443
|
+
ok {sout} == Benchmarker::VERSION + "\n"
|
1444
|
+
end
|
1445
|
+
- spec("[!nrxsb] prints sample code if '-S' option specified.") do
|
1446
|
+
argv = ["-S"]
|
1447
|
+
sout, serr = capture_sio do
|
1448
|
+
pr = proc { Benchmarker.parse_cmdopts(argv) }
|
1449
|
+
ok {pr}.raise?(SystemExit) do |exc|
|
1450
|
+
ok {exc.status} == 0
|
1451
|
+
end
|
1452
|
+
end
|
1453
|
+
ok {serr} == ""
|
1454
|
+
ok {sout} == Benchmarker::Misc.sample_code()
|
1455
|
+
end
|
1456
|
+
- spec("[!s7y6x] keeps command-line options in order to overwirte existing options.") do
|
1457
|
+
ok {Benchmarker::OPTIONS} == {}
|
1458
|
+
argv = "-q -n 1000 -i10 -x2 -I -o tmp.json".split()
|
1459
|
+
Benchmarker.parse_cmdopts(argv)
|
1460
|
+
ok {Benchmarker::OPTIONS} == {
|
1461
|
+
:quiet=>true, :loop=>1000, :iter=>10, :extra=>2,
|
1462
|
+
:inverse=>true, :outfile=>"tmp.json",
|
1463
|
+
}
|
1464
|
+
end
|
1465
|
+
- spec("[!nexi8] option '-w' specifies task name width.") do
|
1466
|
+
ok {Benchmarker::OPTIONS} == {}
|
1467
|
+
Benchmarker.parse_cmdopts(['-w', '10'])
|
1468
|
+
ok {Benchmarker::OPTIONS} == {width: 10}
|
1469
|
+
sout, serr = capture_sio do
|
1470
|
+
Benchmarker.scope(width: 20) do
|
1471
|
+
task "foo" do nil end
|
1472
|
+
end
|
1473
|
+
end
|
1474
|
+
ok {sout} =~ /^foo 0.0000/
|
1475
|
+
end
|
1476
|
+
- spec("[!raki9] option '-n' specifies count of loop.") do
|
1477
|
+
ok {Benchmarker::OPTIONS} == {}
|
1478
|
+
Benchmarker.parse_cmdopts(['-n', '17'])
|
1479
|
+
ok {Benchmarker::OPTIONS} == {loop: 17}
|
1480
|
+
count = 0
|
1481
|
+
sout, serr = capture_sio do
|
1482
|
+
Benchmarker.scope(width: 20) do
|
1483
|
+
task "foo" do count += 1 end
|
1484
|
+
end
|
1485
|
+
end
|
1486
|
+
ok {count} == 17
|
1487
|
+
end
|
1488
|
+
- spec("[!mt7lw] option '-i' specifies number of iteration.") do
|
1489
|
+
ok {Benchmarker::OPTIONS} == {}
|
1490
|
+
Benchmarker.parse_cmdopts(['-i', '5'])
|
1491
|
+
ok {Benchmarker::OPTIONS} == {iter: 5}
|
1492
|
+
count = 0
|
1493
|
+
sout, serr = capture_sio do
|
1494
|
+
Benchmarker.scope(width: 20) do
|
1495
|
+
task "foo" do count += 1 end
|
1496
|
+
end
|
1497
|
+
end
|
1498
|
+
ok {sout} =~ /^## \(#5\)/
|
1499
|
+
ok {sout} !~ /^## \(#6\)/
|
1500
|
+
n = 0
|
1501
|
+
sout.scan(/^## \(#\d+\).*\nfoo +/) do n += 1 end
|
1502
|
+
ok {n} == 5
|
1503
|
+
ok {sout} !~ /^## Removed Min & Max/
|
1504
|
+
ok {sout} =~ /^## Average of 5 +user/
|
1505
|
+
end
|
1506
|
+
- spec("[!7f2k3] option '-x' specifies number of best/worst tasks removed.") do
|
1507
|
+
ok {Benchmarker::OPTIONS} == {}
|
1508
|
+
Benchmarker.parse_cmdopts(['-i', '5', '-x', '1'])
|
1509
|
+
ok {Benchmarker::OPTIONS} == {iter: 5, extra: 1}
|
1510
|
+
count = 0
|
1511
|
+
sout, serr = capture_sio do
|
1512
|
+
Benchmarker.scope(width: 20) do
|
1513
|
+
task "foo" do count += 1 end
|
1514
|
+
end
|
1515
|
+
end
|
1516
|
+
ok {sout} =~ /^## \(#7\)/
|
1517
|
+
ok {sout} !~ /^## \(#8\)/
|
1518
|
+
n = 0
|
1519
|
+
sout.scan(/^## \(#\d+\).*\nfoo +/) do n += 1 end
|
1520
|
+
ok {n} == 7
|
1521
|
+
ok {sout} =~ /^## Removed Min & Max/
|
1522
|
+
ok {sout} =~ /^## Average of 5 \(=7-2\*1\)/
|
1523
|
+
end
|
1524
|
+
- spec("[!r0439] option '-I' specifies inverse switch.") do
|
1525
|
+
ok {Benchmarker::OPTIONS} == {}
|
1526
|
+
Benchmarker.parse_cmdopts(['-I'])
|
1527
|
+
ok {Benchmarker::OPTIONS} == {inverse: true}
|
1528
|
+
sout, serr = capture_sio do
|
1529
|
+
fib = proc {|n| n <= 1 ? n : fib.call(n-1) + fib.call(n-2) }
|
1530
|
+
Benchmarker.scope(width: 20) do
|
1531
|
+
task "foo" do fib.call(15) end
|
1532
|
+
end
|
1533
|
+
end
|
1534
|
+
ok {sout} =~ /^## Ranking real times\/sec$/
|
1535
|
+
ok {sout} =~ /^foo +\d+\.\d+ \(100\.0%\) +\d+\.\d+$/
|
1536
|
+
end
|
1537
|
+
- spec("[!4c73x] option '-o' specifies outout JSON file.") do
|
1538
|
+
ok {Benchmarker::OPTIONS} == {}
|
1539
|
+
outfile = "tmp99.json"
|
1540
|
+
Benchmarker.parse_cmdopts(['-o', outfile])
|
1541
|
+
ok {Benchmarker::OPTIONS} == {outfile: outfile}
|
1542
|
+
at_exit { File.unlink outfile if File.exist?(outfile) }
|
1543
|
+
ok {outfile}.not_exist?
|
1544
|
+
sout, serr = capture_sio do
|
1545
|
+
Benchmarker.scope(width: 20) do
|
1546
|
+
task "foo" do nil end
|
1547
|
+
end
|
1548
|
+
end
|
1549
|
+
ok {outfile}.file_exist?
|
1550
|
+
end
|
1551
|
+
- spec("[!02ml5] option '-q' specifies quiet mode.") do
|
1552
|
+
ok {Benchmarker::OPTIONS} == {}
|
1553
|
+
Benchmarker.parse_cmdopts(['-q', '-i10', '-x1'])
|
1554
|
+
ok {Benchmarker::OPTIONS} == {quiet: true, iter: 10, extra: 1}
|
1555
|
+
count = 0
|
1556
|
+
sout, serr = capture_sio do
|
1557
|
+
Benchmarker.scope(width: 20) do
|
1558
|
+
task "foo" do count += 1 end
|
1559
|
+
end
|
1560
|
+
end
|
1561
|
+
ok {count} == 12
|
1562
|
+
ok {sout} !~ /^## \(#\d\)/
|
1563
|
+
ok {sout} =~ /^## Removed Min & Max/
|
1564
|
+
ok {sout} =~ /^## Average of 10 \(=12-2\*1\)/
|
1565
|
+
end
|
1566
|
+
- spec("[!e5hv0] option '-c' specifies colorize enabled.") do
|
1567
|
+
ok {Benchmarker::OPTIONS} == {}
|
1568
|
+
Benchmarker.parse_cmdopts(['-c'])
|
1569
|
+
ok {Benchmarker::OPTIONS} == {colorize: true}
|
1570
|
+
sout, serr = capture_sio(tty: false) do
|
1571
|
+
Benchmarker.scope() do
|
1572
|
+
task "foo" do nil end
|
1573
|
+
end
|
1574
|
+
end
|
1575
|
+
ok {sout} =~ /\e\[0;36m.*?\e\[0m/
|
1576
|
+
end
|
1577
|
+
- spec("[!e5hv0] option '-c' specifies colorize enabled.") do
|
1578
|
+
ok {Benchmarker::OPTIONS} == {}
|
1579
|
+
Benchmarker.parse_cmdopts(['-C'])
|
1580
|
+
ok {Benchmarker::OPTIONS} == {colorize: false}
|
1581
|
+
sout, serr = capture_sio(tty: true) do
|
1582
|
+
Benchmarker.scope() do
|
1583
|
+
task "foo" do nil end
|
1584
|
+
end
|
1585
|
+
end
|
1586
|
+
ok {sout} !~ /\e\[0;36m.*?\e\[0m/
|
1587
|
+
end
|
1588
|
+
- spec("[!muica] option '-F' specifies filter.") do
|
1589
|
+
ok {Benchmarker::OPTIONS} == {}
|
1590
|
+
Benchmarker.parse_cmdopts(['-F', 'task=ba*'])
|
1591
|
+
ok {Benchmarker::OPTIONS} == {filter: 'task=ba*'}
|
1592
|
+
called = []
|
1593
|
+
sout, serr = capture_sio do
|
1594
|
+
Benchmarker.scope(width: 20) do
|
1595
|
+
task "foo" do called << "foo" end
|
1596
|
+
task "bar", tag: 'curr' do called << "bar" end
|
1597
|
+
task "baz" do called << "baz" end
|
1598
|
+
end
|
1599
|
+
end
|
1600
|
+
ok {called} == ["bar", "baz"]
|
1601
|
+
#
|
1602
|
+
Benchmarker.parse_cmdopts(['-F', 'tag!=curr'])
|
1603
|
+
called = []
|
1604
|
+
sout, serr = capture_sio do
|
1605
|
+
Benchmarker.scope(width: 20) do
|
1606
|
+
task "foo" do called << "foo" end
|
1607
|
+
task "bar", tag: 'curr' do called << "bar" end
|
1608
|
+
task "baz" do called << "baz" end
|
1609
|
+
end
|
1610
|
+
end
|
1611
|
+
ok {called} == ["foo", "baz"]
|
1612
|
+
end
|
1613
|
+
- spec("[!3khc4] sets global variables if long option specified.") do
|
1614
|
+
ok {Benchmarker::OPTIONS} == {}
|
1615
|
+
ok {$opt_blabla} == nil
|
1616
|
+
Benchmarker.parse_cmdopts(['--blabla=123'])
|
1617
|
+
ok {Benchmarker::OPTIONS} == {}
|
1618
|
+
ok {$opt_blabla} == "123"
|
1619
|
+
Benchmarker.parse_cmdopts(['--blabla'])
|
1620
|
+
ok {Benchmarker::OPTIONS} == {}
|
1621
|
+
ok {$opt_blabla} == true
|
1622
|
+
end
|
634
1623
|
end
|
635
|
-
#spec "takes :real, :barchar, and :loop options." do
|
636
|
-
#end
|
637
1624
|
end
|
638
1625
|
|
639
|
-
def test_ranking
|
640
|
-
expected1 = <<'END'
|
641
1626
|
|
642
|
-
|
643
|
-
Yuki 10.5000 (100.0%) ********************
|
644
|
-
Haruhi 11.5000 ( 91.3%) ******************
|
645
|
-
Itsuki 12.5000 ( 84.0%) *****************
|
646
|
-
Kyon 13.5000 ( 77.8%) ****************
|
647
|
-
Mikuru 14.5000 ( 72.4%) **************
|
648
|
-
END
|
649
|
-
expected2 = <<'END'
|
1627
|
+
+ topic(Benchmark) do
|
650
1628
|
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
@r = Benchmarker::Reporter.new(:out=>@out)
|
666
|
-
@stats = Benchmarker::Stats.new(@r, :numerator=>1000*1000)
|
667
|
-
@stats.ranking(@tasks)
|
668
|
-
ok {@out} == expected2
|
1629
|
+
+ topic('.bm()') do
|
1630
|
+
- spec("[!2nf07] defines and runs benchmark.") do
|
1631
|
+
called = {foo: 0, bar: 0}
|
1632
|
+
sout, serr = capture_sio do
|
1633
|
+
Benchmark.bm do |x|
|
1634
|
+
x.report("foo") do called[:foo] += 1 end
|
1635
|
+
x.report("bar") do called[:bar] += 1 end
|
1636
|
+
end
|
1637
|
+
end
|
1638
|
+
ok {called} == {foo: 1, bar: 1}
|
1639
|
+
n = 0
|
1640
|
+
sout.scan(/^## +.*\nfoo +.*\nbar +.*/) { n+= 1 }
|
1641
|
+
ok {n} == 1
|
1642
|
+
ok {serr} == ""
|
669
1643
|
end
|
670
1644
|
end
|
671
|
-
end
|
672
|
-
|
673
|
-
def test_ratio_matrix
|
674
|
-
expected = <<'END'
|
675
1645
|
|
676
|
-
|
677
|
-
[
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
[
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
1646
|
+
+ topic('.bm()') do
|
1647
|
+
- spec("[!ezbb8] defines and runs benchmark twice, reports only 2nd result.") do
|
1648
|
+
called = {foo: 0, bar: 0}
|
1649
|
+
sout, serr = capture_sio do
|
1650
|
+
Benchmark.bmbm do |x|
|
1651
|
+
x.report("foo") do called[:foo] += 1 end
|
1652
|
+
x.report("bar") do called[:bar] += 1 end
|
1653
|
+
end
|
1654
|
+
end
|
1655
|
+
ok {called} == {foo: 2, bar: 2}
|
1656
|
+
n = 0
|
1657
|
+
sout.scan(/^## +.*\nfoo +.*\nbar +.*/) { n+= 1 }
|
1658
|
+
ok {n} == 1
|
1659
|
+
ok {serr} == ""
|
1660
|
+
end
|
686
1661
|
end
|
687
|
-
end
|
688
1662
|
|
689
|
-
end
|
1663
|
+
end
|
690
1664
|
|
691
1665
|
|
692
|
-
if __FILE__ == $0
|
693
|
-
Oktest::run_all()
|
694
1666
|
end
|