rgot 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0bd2d7a31146606c28b7b373c1f05632088ba374
4
- data.tar.gz: 14a9e7bf677e9eb24ea70d3710a48f6383d8b7ad
3
+ metadata.gz: b55640e6b13205e65a7e08765579b3566f43b385
4
+ data.tar.gz: 2b9727ef0256af4d11d272f2c4aa255ecf91053c
5
5
  SHA512:
6
- metadata.gz: b912a04b6c18f16b8660d2eefb0a50a0444fd1fd60c7d68292d2fdab77f4bf6de63874f86d05346749bbf5c397a195b5247da17089a71c0558dd2b22ce9dde1b
7
- data.tar.gz: cc789d6941cb34fc8b0fc1acb1c5844d3a157c69811b5c08e83c04126cdfd38e563fb8f7a1ebaee0c495aa72c1d4f2dc91b815e4ec695c18a84b07caa130ea39
6
+ metadata.gz: ce0a920a44014f5b876382e6091018a1b447d9acd96e460e9077640e07047907221cc4b9946f849b09efcc0cbf65b881b78e8d88b100cf197ac2ebf53eb865c7
7
+ data.tar.gz: 516c281575d0fa554698adb4cd2e69af664670dba015922c31c7f9dcf67f874715adbd190cf3482e2bd9a08d99a10a50d6e44dcd728cf875ca783516e6bbbfea
data/README.md CHANGED
@@ -83,6 +83,12 @@ module FooTest
83
83
  end
84
84
  ```
85
85
 
86
+ ```
87
+ $ rgot foo_test.rb --bench .
88
+ benchmark_something 14400000 81.392 ns/op
89
+ ok FooTest 2.782s
90
+ ```
91
+
86
92
  `b.n` is automatically adjusted.
87
93
 
88
94
  ## Example
@@ -141,14 +147,17 @@ But all file should be have one module (like golang package name).
141
147
 
142
148
  ```ruby
143
149
  module XxxTest
150
+ # ...
144
151
  end
145
152
  ```
146
153
 
147
154
  ## Method name
148
155
 
149
- Method name should be set 'test_*' for testing.
156
+ Method name should be set `test_*` for testing.
150
157
 
151
- And benchmark method should be set 'benchmark_*'.
158
+ And benchmark method should be set `benchmark_*`.
159
+
160
+ And example method should be set `example_*`.
152
161
 
153
162
  ```ruby
154
163
  module XxxTest
@@ -157,10 +166,13 @@ module XxxTest
157
166
 
158
167
  def benchmark_any_name(b)
159
168
  end
169
+
170
+ def example_any_name
171
+ end
160
172
  end
161
173
  ```
162
174
 
163
- # Command
175
+ # Command line interface
164
176
 
165
177
  ```
166
178
  $ rgot -h
@@ -169,6 +181,8 @@ Usage: rgot [options]
169
181
  --bench [regexp] benchmark
170
182
  --benchtime [sec] benchmark running time
171
183
  --timeout [sec] set timeout sec to testing
184
+ --cpu [count,...] set cpu counts of comma splited
185
+ --thread [count,...] set thread counts of comma splited
172
186
  --require [path] load some code before running
173
187
  --load-path [path] Specify $LOAD_PATH directory
174
188
  ```
@@ -217,6 +231,41 @@ Run testing with benchmark.
217
231
 
218
232
  Set `someone` if you only run benchmark to match `someone` method.(e.g. benchmark_someone_1)
219
233
 
234
+ ### Parallel benchmark
235
+
236
+ Benchmark for parallel performance.
237
+
238
+ `--cpu` option set process counts (default 1).
239
+
240
+ And `--thread` option set thread counts (default 1).
241
+
242
+ Benchmark fork, run and report each by process counts.
243
+
244
+ (**process** and **thread** means ruby/linux process)
245
+
246
+ ```ruby
247
+ module FooTest
248
+ def benchmark_any_func(b)
249
+ b.run_parallel do |pb|
250
+ # pb is instance of Rgot::PB
251
+ # call some time by b.n
252
+ while pb.next
253
+ some_func()
254
+ end
255
+ end
256
+ end
257
+ end
258
+ ```
259
+
260
+ ```
261
+ $ rgot foo_test.rb --bench . --cpu=2,4 --thread=2,4
262
+ benchmark_any_func-2(2) 40 13363604.899 ns/op
263
+ benchmark_any_func-2(4) 160 7125845.113 ns/op
264
+ benchmark_any_func-4(2) 160 7224815.534 ns/op
265
+ benchmark_any_func-4(4) 320 3652431.962 ns/op
266
+ ok FooTest 3.061s
267
+ ```
268
+
220
269
  ## Timeout
221
270
 
222
271
  ```
@@ -322,10 +371,10 @@ Automatic number calculated by running time.
322
371
  Recommend to this idiom.
323
372
 
324
373
  ```ruby
325
- def benchmark_someone(b)
374
+ def benchmark_something(b)
326
375
  i = 0
327
376
  while i < b.n
328
- someone()
377
+ something()
329
378
  i += 1
330
379
  end
331
380
  end
@@ -335,6 +384,18 @@ end
335
384
 
336
385
  Reset benchmark timer
337
386
 
387
+ ```ruby
388
+ def benchmark_something(b)
389
+ obj = heavy_prepare_method()
390
+ b.reset_timer # you can ignore time of havy_prepare_method()
391
+ i = 0
392
+ while i < b.n
393
+ obj.something()
394
+ i += 1
395
+ end
396
+ end
397
+ ```
398
+
338
399
  ## Rgot::B#start_timer
339
400
 
340
401
  Start benchmark timer
@@ -342,3 +403,31 @@ Start benchmark timer
342
403
  ## Rgot::B#stop_timer
343
404
 
344
405
  Stop benchmark timer
406
+
407
+ ## Rgot::B#run_parallel
408
+
409
+ Start parallel benchmark using `fork` and `Thread.new`.
410
+
411
+ This method should be call with block.
412
+
413
+ The block argument is instance of Rgot::PB.
414
+
415
+ # Rgot::PB (Parallel Benchmark)
416
+
417
+ ## Rgot::PB#next
418
+
419
+ Should be call this when parallel benchmark.
420
+
421
+ Repeat while return false.
422
+
423
+ Recommend this idiom.
424
+
425
+ ```ruby
426
+ def benchmark_foo(b)
427
+ b.run_parallel do |pb|
428
+ while pb.next
429
+ some_func()
430
+ end
431
+ end
432
+ end
433
+ ```
data/bin/rgot CHANGED
@@ -21,6 +21,12 @@ parser = OptionParser.new do |o|
21
21
  o.on '--timeout [sec]', "set timeout sec to testing" do |arg|
22
22
  opts[:timeout] = arg
23
23
  end
24
+ o.on '--cpu [count,...]', "set cpu counts of comma splited" do |arg|
25
+ opts[:cpu] = arg
26
+ end
27
+ o.on '--thread [count,...]', "set thread counts of comma splited" do |arg|
28
+ opts[:thread] = arg
29
+ end
24
30
  o.on '--require [path]', "load some code before running" do |arg|
25
31
  opts[:require_paths] << arg
26
32
  end
@@ -91,9 +97,19 @@ modules.each do |test_module|
91
97
  at_exit {
92
98
  template = "%s\t%s\t%.3fs"
93
99
 
94
- if $!.kind_of?(SystemExit) && $!.success?
95
- puts sprintf(template, "ok", test_module, Rgot.now - duration)
100
+ case $!
101
+ when SystemExit
102
+ if $!.success?
103
+ # exit 0
104
+ puts sprintf(template, "ok", test_module, Rgot.now - duration)
105
+ else
106
+ # exit 1
107
+ puts sprintf(template, "FAIL", test_module, Rgot.now - duration)
108
+ end
109
+ when NilClass
110
+ # not raise, not exit
96
111
  else
112
+ # any exception
97
113
  puts sprintf(template, "FAIL", test_module, Rgot.now - duration)
98
114
  end
99
115
  }
@@ -4,6 +4,8 @@ module Rgot
4
4
  require 'rgot/m'
5
5
  require 'rgot/t'
6
6
  require 'rgot/b'
7
+ require 'rgot/pb'
8
+ require 'rgot/benchmark_result'
7
9
  require 'rgot/example_parser'
8
10
 
9
11
  class OptionError < StandardError
@@ -31,5 +33,9 @@ module Rgot
31
33
  Time.now
32
34
  end
33
35
  end
36
+
37
+ def benchmark(opts={}, &block)
38
+ B.new(nil, nil, opts).run(&block)
39
+ end
34
40
  end
35
41
  end
@@ -1,16 +1,15 @@
1
1
  module Rgot
2
2
  class B < Common
3
3
  attr_accessor :n
4
- def initialize(benchmark_module, name, opts)
4
+ def initialize(benchmark_module, name, opts={})
5
5
  super()
6
6
  @n = 1
7
7
  @module = benchmark_module
8
8
  @name = name
9
9
  @opts = opts
10
- @benchtime = @opts.fetch(:benchtime, 1).to_f
11
10
  @timer_on = false
12
11
  @duration = 0
13
- @module.extend @module
12
+ @module.extend @module if @module
14
13
  end
15
14
 
16
15
  def start_timer
@@ -34,43 +33,61 @@ module Rgot
34
33
  @duration = 0
35
34
  end
36
35
 
37
- def run
36
+ def run(&block)
38
37
  n = 1
39
- run_n(n)
40
- while !failed? && @duration < @benchtime && @n < 1e9
41
- if @duration < (@benchtime / 100.0)
42
- n *= 100
43
- elsif @duration < (@benchtime / 10.0)
44
- n *= 10
45
- elsif @duration < (@benchtime / 5.0)
46
- n *= 5
47
- elsif @duration < (@benchtime / 2.0)
48
- n *= 2
38
+ benchtime = @opts.fetch(:benchtime, 1).to_f
39
+ run_n(n.to_i, block)
40
+ while !failed? && @duration < benchtime && @n < 1e9
41
+ if @duration < (benchtime / 100.0)
42
+ @n *= 100
43
+ elsif @duration < (benchtime / 10.0)
44
+ @n *= 10
45
+ elsif @duration < (benchtime / 5.0)
46
+ @n *= 5
47
+ elsif @duration < (benchtime / 2.0)
48
+ @n *= 2
49
49
  else
50
- n *= 1.2
50
+ if @n.to_i == 1
51
+ break
52
+ end
53
+ @n *= 1.2
51
54
  end
52
- run_n(n)
55
+ run_n(@n.to_i, block)
53
56
  end
57
+
58
+ BenchmarkResult.new(n: @n, t: @duration)
54
59
  end
55
60
 
56
- def report
57
- printf("%s\t%d\t%.3f ns/op\n", @name, @n, @duration / @n * 1_000_000_000)
61
+ def run_parallel
62
+ raise LocalJumpError, "no block given" unless block_given?
63
+
64
+ @opts[:procs].times do
65
+ fork {
66
+ Array.new(@opts[:threads]) {
67
+ Thread.new {
68
+ yield PB.new(bn: @n)
69
+ }.tap { |t| t.abort_on_exception = true }
70
+ }.each(&:join)
71
+ }
72
+ end
73
+ @n *= @opts[:procs] * @opts[:threads]
74
+ Process.waitall
58
75
  end
59
76
 
60
77
  private
61
78
 
62
- def run_n(n)
79
+ def run_n(n, block=nil)
63
80
  GC.start
64
81
  i = 0
65
82
  @n = n
66
83
  reset_timer
67
84
  start_timer
68
- call
85
+ if block
86
+ block.call(self)
87
+ else
88
+ @module.instance_method(@name).bind(@module).call(self)
89
+ end
69
90
  stop_timer
70
91
  end
71
-
72
- def call
73
- @module.instance_method(@name).bind(@module).call(self)
74
- end
75
92
  end
76
93
  end
@@ -0,0 +1,15 @@
1
+ module Rgot
2
+ class BenchmarkResult
3
+ # Ruby-2.0.0 wants default value of keyword_argument
4
+ def initialize(n: nil, t: nil)
5
+ raise ArgumentError, "missing keyword: n" unless n
6
+ raise ArgumentError, "missing keyword: t" unless t
7
+ @n = n
8
+ @t = t
9
+ end
10
+
11
+ def to_s
12
+ sprintf("%d\t%.3f ns/op", @n, @t / @n * 1_000_000_000)
13
+ end
14
+ end
15
+ end
@@ -3,11 +3,29 @@ require 'stringio'
3
3
  module Rgot
4
4
  class M
5
5
  # Ruby-2.0.0 wants default value of keyword_argument
6
- def initialize(tests: [], benchmarks: [], examples: [], opts: {})
6
+ def initialize(tests: nil, benchmarks: nil, examples: nil, opts: {})
7
+ raise ArgumentError, "missing keyword: tests" unless tests
8
+ raise ArgumentError, "missing keyword: benchmarks" unless benchmarks
9
+ raise ArgumentError, "missing keyword: examples" unless examples
10
+
7
11
  @tests = tests
8
12
  @benchmarks = benchmarks
9
13
  @examples = examples
10
14
  @opts = opts
15
+ @cpu_list = @opts.fetch(:cpu, "1").split(',').map { |i|
16
+ j = i.to_i
17
+ if j == 0
18
+ raise OptionError, "expect integer string, got #{i.inspect}"
19
+ end
20
+ j
21
+ }
22
+ @thread_list = @opts.fetch(:thread, "1").split(',').map { |i|
23
+ j = i.to_i
24
+ if j == 0
25
+ raise OptionError, "expect integer string, got #{i.inspect}"
26
+ end
27
+ j
28
+ }
11
29
  end
12
30
 
13
31
  def run
@@ -51,11 +69,23 @@ module Rgot
51
69
  @benchmarks.each do |bench|
52
70
  next unless /#{@opts[:bench]}/ =~ bench.name
53
71
 
54
- b = B.new(bench.module, bench.name.to_sym, @opts)
55
- b.run
56
- b.report
57
- if b.failed?
58
- ok = false
72
+ @cpu_list.each do |procs|
73
+ @thread_list.each do |threads|
74
+ opts = @opts.dup
75
+ opts[:procs] = procs
76
+ opts[:threads] = threads
77
+ b = B.new(bench.module, bench.name.to_sym, opts)
78
+
79
+ benchname = bench.name.to_s
80
+ benchname << "-#{procs}" if 1 < procs
81
+ benchname << "(#{threads})" if 1 < threads
82
+ print "#{benchname}\t"
83
+ result = b.run
84
+ puts result
85
+ if b.failed?
86
+ ok = false
87
+ end
88
+ end
59
89
  end
60
90
  end
61
91
  ok
@@ -88,6 +118,8 @@ module Rgot
88
118
  end
89
119
 
90
120
  def capture
121
+ raise LocalJumpError, "no block given" unless block_given?
122
+
91
123
  orig_out, orig_err = $stdout, $stderr
92
124
  out, err = StringIO.new, StringIO.new
93
125
  $stdout, $stderr = out, err
@@ -0,0 +1,15 @@
1
+ module Rgot
2
+ class PB
3
+ attr_accessor :bn
4
+
5
+ # Ruby-2.0.0 wants default value of keyword_argument
6
+ def initialize(bn: nil)
7
+ raise ArgumentError, "missing keyword: bn" unless bn
8
+ @bn = bn
9
+ end
10
+
11
+ def next
12
+ (0 < @bn).tap { @bn -= 1 }
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Rgot
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rgot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-15 00:00:00.000000000 Z
11
+ date: 2015-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -55,9 +55,11 @@ files:
55
55
  - bin/rgot
56
56
  - lib/rgot.rb
57
57
  - lib/rgot/b.rb
58
+ - lib/rgot/benchmark_result.rb
58
59
  - lib/rgot/common.rb
59
60
  - lib/rgot/example_parser.rb
60
61
  - lib/rgot/m.rb
62
+ - lib/rgot/pb.rb
61
63
  - lib/rgot/t.rb
62
64
  - lib/rgot/version.rb
63
65
  - rgot.gemspec
@@ -81,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
83
  version: '0'
82
84
  requirements: []
83
85
  rubyforge_project:
84
- rubygems_version: 2.4.5
86
+ rubygems_version: 2.4.5.1
85
87
  signing_key:
86
88
  specification_version: 4
87
89
  summary: Ruby + Golang Testing = Rgot