rgot 0.0.4 → 0.0.5

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 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