benchmark-interface 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +39 -0
  3. data/Gemfile +2 -0
  4. data/LICENCE +7 -0
  5. data/README.md +237 -0
  6. data/benchmark-interface.gemspec +20 -0
  7. data/bin/benchmark +15 -0
  8. data/examples/bench9000.rb +23 -0
  9. data/examples/bench9000micro.rb +31 -0
  10. data/examples/benchmark.rb +40 -0
  11. data/examples/bips.rb +34 -0
  12. data/examples/clamp.rb +17 -0
  13. data/examples/interface.rb +13 -0
  14. data/examples/long.rb +9 -0
  15. data/examples/mri.rb +15 -0
  16. data/examples/perfer.rb +25 -0
  17. data/examples/rbench.rb +46 -0
  18. data/examples/readme.rb +12 -0
  19. data/examples/script.rb +14 -0
  20. data/lib/benchmark-interface.rb +40 -0
  21. data/lib/benchmark-interface/backends/bench9000.rb +87 -0
  22. data/lib/benchmark-interface/backends/benchmark.rb +68 -0
  23. data/lib/benchmark-interface/backends/bips.rb +49 -0
  24. data/lib/benchmark-interface/backends/simple.rb +38 -0
  25. data/lib/benchmark-interface/benchmark-set.rb +85 -0
  26. data/lib/benchmark-interface/benchmark.rb +72 -0
  27. data/lib/benchmark-interface/frontends/bench9000.rb +21 -0
  28. data/lib/benchmark-interface/frontends/bench9000micro.rb +19 -0
  29. data/lib/benchmark-interface/frontends/benchmark.rb +50 -0
  30. data/lib/benchmark-interface/frontends/bips.rb +40 -0
  31. data/lib/benchmark-interface/frontends/mri.rb +84 -0
  32. data/lib/benchmark-interface/frontends/perfer.rb +27 -0
  33. data/lib/benchmark-interface/frontends/rbench.rb +64 -0
  34. data/lib/benchmark-interface/require.rb +38 -0
  35. data/lib/benchmark-interface/run.rb +111 -0
  36. data/lib/benchmark-interface/version.rb +13 -0
  37. data/tests/expected/bench9000-bips.txt +8 -0
  38. data/tests/expected/bench9000-bm.txt +2 -0
  39. data/tests/expected/bench9000-bmbm.txt +2 -0
  40. data/tests/expected/bench9000-simple.txt +2 -0
  41. data/tests/expected/bench9000micro-bips.txt +8 -0
  42. data/tests/expected/bench9000micro-bm.txt +2 -0
  43. data/tests/expected/bench9000micro-bmbm.txt +2 -0
  44. data/tests/expected/bench9000micro-simple.txt +2 -0
  45. data/tests/expected/benchmark-bips.txt +72 -0
  46. data/tests/expected/benchmark-bm.txt +12 -0
  47. data/tests/expected/benchmark-bmbm.txt +12 -0
  48. data/tests/expected/benchmark-simple.txt +22 -0
  49. data/tests/expected/bips-bips.txt +2 -0
  50. data/tests/expected/bips-bm.txt +7 -0
  51. data/tests/expected/bips-bmbm.txt +7 -0
  52. data/tests/expected/bips-simple.txt +11 -0
  53. data/tests/expected/interface-bips.txt +24 -0
  54. data/tests/expected/interface-bm.txt +4 -0
  55. data/tests/expected/interface-bmbm.txt +4 -0
  56. data/tests/expected/interface-simple.txt +6 -0
  57. data/tests/expected/long-bips.txt +9 -0
  58. data/tests/expected/long-bm.txt +2 -0
  59. data/tests/expected/long-bmbm.txt +2 -0
  60. data/tests/expected/long-simple.txt +2 -0
  61. data/tests/expected/mri-bips.txt +9 -0
  62. data/tests/expected/mri-bm.txt +2 -0
  63. data/tests/expected/mri-bmbm.txt +2 -0
  64. data/tests/expected/mri-simple.txt +2 -0
  65. data/tests/expected/perfer-bips.txt +20 -0
  66. data/tests/expected/perfer-bm.txt +4 -0
  67. data/tests/expected/perfer-bmbm.txt +4 -0
  68. data/tests/expected/perfer-simple.txt +5 -0
  69. data/tests/expected/rbench-bips.txt +42 -0
  70. data/tests/expected/rbench-bm.txt +7 -0
  71. data/tests/expected/rbench-bmbm.txt +7 -0
  72. data/tests/expected/rbench-simple.txt +12 -0
  73. data/tests/expected/readme-bips.txt +18 -0
  74. data/tests/expected/readme-bm.txt +3 -0
  75. data/tests/expected/readme-bmbm.txt +3 -0
  76. data/tests/expected/readme-simple.txt +4 -0
  77. data/tests/expected/script-bips.txt +18 -0
  78. data/tests/expected/script-bm.txt +3 -0
  79. data/tests/expected/script-bmbm.txt +3 -0
  80. data/tests/expected/script-simple.txt +4 -0
  81. data/tests/rewritten/mri.rb +15 -0
  82. data/tests/tests.rb +73 -0
  83. data/tests/tools/squash.rb +63 -0
  84. metadata +130 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4d8189a13342cdf88c0edd26ea4f45aa75cf2885
4
+ data.tar.gz: b8421da8f6de75944ee3e9e0e442ccfd57ee1239
5
+ SHA512:
6
+ metadata.gz: 151985c795552fa31b9164ba1b5eb1515d7586715617b7ca3b6472961f059374a83b492bdd6eabf1f515ab4577e7e4e6ebf7cf596817cc85ee97f32ba562a152
7
+ data.tar.gz: 0947f0a019c38c4a73250e899ef837f762cd2a99e105c3fcf8407cd20d5ebf661a66dec4d012241a95595769eac242f46b35aeddaafaeca92d173e85412aa970
@@ -0,0 +1,39 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - ruby-1.8.7-p371
5
+ - ruby-1.9.3-p547
6
+ - ruby-2.0.0-p648
7
+ - ruby-2.1.10
8
+ - ruby-2.2.5
9
+ - ruby-2.3.1
10
+ - ruby-head
11
+ - jruby-1.7.25
12
+ - jruby-9.0.5.0
13
+ - jruby-9.1.0.0
14
+ - jruby-head
15
+ - rbx-2.71828182
16
+ - rbx-3.29
17
+
18
+ install:
19
+ - gem install benchmark-ips || echo skipping benchmark-ips
20
+ - gem install parser || echo skipping parser
21
+ - gem install unparser || echo skipping unparser
22
+
23
+ env:
24
+ - BACKEND=simple
25
+ - BACKEND=bm
26
+ - BACKEND=bmbm
27
+ - BACKEND=bips
28
+
29
+ matrix:
30
+ include:
31
+ - rvm: ruby-2.3.1
32
+ install:
33
+ - curl -Ol http://builds.topazruby.com/topaz-linux64-019daf03d75e32124c2dfd282915b49c35f27289.tar.bz2
34
+ - tar -jxf topaz-linux64-019daf03d75e32124c2dfd282915b49c35f27289.tar.bz2
35
+ env:
36
+ - TEST_RUBY=topaz/bin/topaz
37
+ - BACKEND=simple
38
+
39
+ script: tests/tests.rb --$BACKEND
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENCE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
2
+ code is released under a tri EPL/GPL/LGPL license. You can use it,
3
+ redistribute it and/or modify it under the terms of the:
4
+
5
+ Eclipse Public License version 1.0
6
+ GNU General Public License version 2
7
+ GNU Lesser General Public License version 2.1
@@ -0,0 +1,237 @@
1
+ # Benchmark-Interface
2
+
3
+ ## Introduction
4
+
5
+ Benchmark-Interface is one Ruby benchmarking interface to rule them all. It
6
+ allows you to run benchmarks written for one Ruby benchmarking system using some
7
+ other Ruby benchmarking system.
8
+
9
+ For example, Benchmark-Interface lets you take a benchmark from MRI's suite and
10
+ run it using `benchmark-ips`, or take a benchmark written using Bench9000 and
11
+ run it using `bmbm`.
12
+
13
+ Benchmark-Interface also provides a new format for writing benchmarks, which is
14
+ designed to be the simplest of all, making it easy to write lots of new
15
+ benchmarks and run them any way you like.
16
+
17
+ ```
18
+ $ gem install benchmark-interface
19
+ ```
20
+
21
+ Benchmark-Interface doesn't install any backends (other benchmark tools) by
22
+ default, so you probably also want to do:
23
+
24
+ ```
25
+ $ gem install benchmark-ips
26
+ ```
27
+
28
+ ## Examples
29
+
30
+ ### Running an MRI benchmark using `benchmark-ips`
31
+
32
+ ```
33
+ $ benchmark ruby/benchmark/bm_vm1_length.rb
34
+
35
+ These are long benchmarks - we're increasing warmup and sample time
36
+ Warming up --------------------------------------
37
+ bm_vm1_length 1.000 i/100ms
38
+ bm_vm1_length 1.000 i/100ms
39
+ bm_vm1_length 1.000 i/100ms
40
+ Calculating -------------------------------------
41
+ bm_vm1_length 0.955 (± 0.0%) i/s - 10.000 in 10.472341s
42
+ bm_vm1_length 0.960 (± 0.0%) i/s - 10.000 in 10.433246s
43
+ bm_vm1_length 0.975 (± 0.0%) i/s - 10.000 in 10.260680s
44
+ ```
45
+
46
+ ### Running a `bench9000` benchmark using `bmbm`
47
+
48
+ ```
49
+ $ benchmark bench9000/benchmarks/classic/mandelbrot.rb --bmbm
50
+
51
+ user system total real
52
+ mandelbrot 1.760000 0.030000 1.790000 ( 1.804423)
53
+ ```
54
+
55
+ ## The Benchmark-Interface Interface
56
+
57
+ Benchmark-Interface provides its own new format for writing benchmarks. It's
58
+ very simple.
59
+
60
+ ```ruby
61
+ benchmark { 14 * 14 * 14 }
62
+ benchmark { 14 ** 3 }
63
+ ```
64
+
65
+ You can give benchmarks names, and you usually should, but they will be named
66
+ with the file name and a counter if you don't.
67
+
68
+ ```ruby
69
+ benchmark('mul') { 14 * 14 * 14 }
70
+ benchmark('pow') { 14 ** 3 }
71
+ ```
72
+
73
+ You just write that in the file. You don't need to require anything. We talk
74
+ about all the benchmarks in a file being the 'benchmark set'.
75
+
76
+ If `benchmark` is for some reason overloaded, you can also use
77
+ `Benchmark-Interface.benchmark`.
78
+
79
+ ## Frontends
80
+
81
+ If you already have benchmarks written for a different system you can run those
82
+ with Benchmark-Interface.
83
+
84
+ Supported frontends are:
85
+
86
+ * Benchmark-Interface
87
+ * MRI's benchmarks
88
+ * The `benchmark` standard library (`measure`, `bm`, `bmbm` and so on)
89
+ * RBench
90
+ * Perfer
91
+ * `benchmark-ips`
92
+ * `bench9000`
93
+
94
+ ### Notes on specific frontends
95
+
96
+ #### Benchmark-Interface
97
+
98
+ As well as normal usage, you can also `require 'benchmark-interface'` at the top
99
+ of your file of benchmarks, and then run the file as a normal Ruby script. This
100
+ will have the same effect as `benchmark file.rb` (and so will run
101
+ `benchmark-ips` as the backend).
102
+
103
+ #### MRI's benchmarks
104
+
105
+ To run MRI's benchmarks you need two extra gems.
106
+
107
+ ```
108
+ $ gem install parser unparser
109
+ ```
110
+
111
+ For MRI's benchmarks we detect the last statement, which is usually a `while`
112
+ loop and wrap that in a Benchmark-Interface block. If we see a variable being
113
+ initialised and then used in the last statement, we copy that into the block.
114
+ This doesn't work in all cases, but it does in most. The `--show-rewrite` option
115
+ shows you what we are doing. Please file a bug if we're getting it wrong for any
116
+ benchmarks in the MRI repository.
117
+
118
+ Running MRI's benchmarks requires rewriting their source code, which means
119
+ running the fairly complex `parser` and `unparser` gems. This is a bit much to
120
+ ask of new Ruby implementations, so you can do the rewriting using another
121
+ implementation and get it to cache the result for the real implementation. The
122
+ file is written to `mri-rewrite-cache.rb` in the current directory.
123
+
124
+ ```
125
+ $ rbenv shell 2.3.1
126
+ $ benchmark ruby/benchmark/bm_vm1_length.rb --cache
127
+ $ rbenv shell topaz-dev
128
+ $ benchmark ruby/benchmark/bm_vm1_length.rb --use-cache
129
+ ```
130
+
131
+ #### `benchmark-ips` and Perfer
132
+
133
+ Both `benchmark-ips` and Perfer allow you to write benchmarked blocks which
134
+ take a number of iterations. This is done to reduce the overhead of calling
135
+ the block by putting the iterations loop (presumably a `while` loop, so not
136
+ itself involving another block) inside the benchmarked code. However this isn't
137
+ supported by other backends. To make this work, we look at how many iterations
138
+ are needed to make the benchmark run for about a second and always run that
139
+ many iterations. The number of iterations is the same for all benchmarks, and
140
+ we take the smallest number, as the larger number can be unbound and make
141
+ some benchmarks take a very long time.
142
+
143
+ ## Backends
144
+
145
+ When you have a file of benchmarks, you can run it using different Ruby
146
+ benchmarking systems. By default, it will run your benchmarks with
147
+ `benchmark/ips`, which is usually the best choice.
148
+
149
+ Supported backends are:
150
+
151
+ * Simple looping, via `--simple`
152
+ * `bm`, via `--bm`
153
+ * `bmbm`, via `--bmbm`
154
+ * `benchmark-ips`, via `--bips`
155
+ * `bench9000`, via `--bench9000`
156
+
157
+ ### Notes on specific backends
158
+
159
+ #### Simple looping
160
+
161
+ Simple looping does the simplest thing possible and runs your benchmark in a
162
+ loop printing the iterations per second as it goes. By default it runs for
163
+ 10s, but you can use options like `--time 60` to run for 60 seconds.
164
+
165
+ #### `bm` and `bmbm`
166
+
167
+ `bm` and `bmbm` only run your benchmark once when timing, which isn't what
168
+ benchmarks written for `benchmark-ips` expect. Therefore if a benchmark takes
169
+ less than a tenth of a second it is run several times so that it takes about a
170
+ second. The number of iterations is the same for all benchmarks in the same set
171
+ and is printed as the set starts.
172
+
173
+ You can turn this off with `--no-scale`
174
+
175
+ #### `benchmark-ips`
176
+
177
+ We run with `x.iterations = 3` by default.
178
+
179
+ If a benchmark takes more than a tenth of a second, the warmup and sampling
180
+ periods of `benchmark-ips` will be increased, as by default `benchmark-ips` is
181
+ set up for quicker benchmarks that complete many iterations in a second.
182
+
183
+ You can turn this off with `--no-scale`.
184
+
185
+ You'll need to manually install the `benchmark-ips` gem.
186
+
187
+ #### Bench9000
188
+
189
+ Using Bench9000 as a backend is a little more complex. You need to define a
190
+ configuration file which runs `benchmark` with the benchmark file, the
191
+ `--bench9000` flag and the name of the benchmark, and then you separately run
192
+ the `bench9000` command.
193
+
194
+ ```
195
+ benchmark 'clamp_a', 'benchmark examples/benchmark-interface.rb --bench9000 clamp_a'
196
+ benchmark 'clamp_b', 'benchmark examples/benchmark-interface.rb --bench9000 clamp_b'
197
+ ```
198
+
199
+ ```
200
+ $ bench9000 detail --config bench9000.config 2.3.0 clamp_a clamp_b --value-per-line
201
+ ```
202
+
203
+ The Bench9000 has the same scaling functionality as `bm`, but here it switches
204
+ to the micro-harness. Turn it off with `--no-scale`.
205
+
206
+ You'll need to manually install the Bench9000 gem.
207
+
208
+ ## Supported Ruby Implementations
209
+
210
+ Tested versions are in brackets.
211
+
212
+ * MRI (1.8.7-p371, 1.9.3-p547, 2.0.0-p648, 2.1.10, 2.2.5, 2.3.1, head)
213
+ * JRuby (1.7.25, 9.0.5.0, 9.1.0.0, head)
214
+ * JRuby+Truffle
215
+ * Rubinius (2.71828182, 3.29)
216
+ * Topaz
217
+
218
+ Benchmark-Interface is designed to be gentle on new implementations of Ruby and
219
+ should hopefully be relatively easy to get working if you are writing one.
220
+
221
+ One major limitation is that the `unparser` gem doesn't work with Ruby versions
222
+ below 1.9. You can get around this by caching the translation result with a
223
+ supported version of Ruby (the `--cache` option) and then using that cached
224
+ translation in the version of Ruby you are benchmarking (the `--use-cache`
225
+ option).
226
+
227
+ You also need to install these gems manually if you want to translate MRI
228
+ benchmarks.
229
+
230
+ ## Caveats
231
+
232
+ * This tool does nothing to address the risk of inputs being constant folded or
233
+ results discarded.
234
+ * Don't compare results from two different benchmarking backends.
235
+ * Some automated things we do like scaling and setting iterations can
236
+ complicate benchmarking.
237
+ * Use your own scientific judgement!
@@ -0,0 +1,20 @@
1
+ require File.expand_path('lib/benchmark-interface/version', File.dirname(__FILE__))
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'benchmark-interface'
5
+ spec.version = BenchmarkInterface::VERSION
6
+ spec.authors = ['Chris Seaton']
7
+ spec.email = ['chris@chrisseaton.com']
8
+ spec.summary = 'One Ruby benchmarking interface to rule them all'
9
+ spec.homepage = 'https://github.com/jruby/benchmark-interface'
10
+ spec.description = 'A new format for writing Ruby benchmarks, and a tool ' \
11
+ 'that lets you run benchmarks written in many formats ' \
12
+ 'with many different benchmarking tools'
13
+ spec.licenses = ['EPL-1.0', 'GPL-2.0', 'LGPL-2.1']
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.test_files = spec.files.grep(%r{^test/})
17
+ spec.require_paths = ['lib']
18
+ spec.bindir = 'bin'
19
+ spec.executables = ['benchmark']
20
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
4
+ # code is released under a tri EPL/GPL/LGPL license. You can use it,
5
+ # redistribute it and/or modify it under the terms of the:
6
+ #
7
+ # Eclipse Public License version 1.0
8
+ # GNU General Public License version 2
9
+ # GNU Lesser General Public License version 2.1
10
+
11
+ $LOAD_PATH.push File.expand_path('../../lib', __FILE__)
12
+
13
+ require 'benchmark-interface'
14
+
15
+ BenchmarkInterface.run ARGV
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
2
+ # code is released under a tri EPL/GPL/LGPL license. You can use it,
3
+ # redistribute it and/or modify it under the terms of the:
4
+ #
5
+ # Eclipse Public License version 1.0
6
+ # GNU General Public License version 2
7
+ # GNU Lesser General Public License version 2.1
8
+
9
+ require File.expand_path('clamp', File.dirname(__FILE__))
10
+
11
+ def harness_input
12
+ [10, 40, 90]
13
+ end
14
+
15
+ def harness_sample(input)
16
+ clamp_a(*input)
17
+ end
18
+
19
+ def harness_verify(output)
20
+ output == 40
21
+ end
22
+
23
+ require 'bench9000/harness'
@@ -0,0 +1,31 @@
1
+ # Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
2
+ # code is released under a tri EPL/GPL/LGPL license. You can use it,
3
+ # redistribute it and/or modify it under the terms of the:
4
+ #
5
+ # Eclipse Public License version 1.0
6
+ # GNU General Public License version 2
7
+ # GNU Lesser General Public License version 2.1
8
+
9
+ require File.expand_path('clamp', File.dirname(__FILE__))
10
+
11
+ def micro_harness_input
12
+ [10, 40, 90]
13
+ end
14
+
15
+ def micro_harness_iterations
16
+ 50_000_000
17
+ end
18
+
19
+ def micro_harness_sample(input)
20
+ clamp_a(*input)
21
+ end
22
+
23
+ def micro_harness_expected
24
+ sum = 0
25
+ micro_harness_iterations.times do
26
+ sum = (sum + 40) % 149
27
+ end
28
+ sum
29
+ end
30
+
31
+ require 'bench9000/micro-harness'
@@ -0,0 +1,40 @@
1
+ # Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
2
+ # code is released under a tri EPL/GPL/LGPL license. You can use it,
3
+ # redistribute it and/or modify it under the terms of the:
4
+ #
5
+ # Eclipse Public License version 1.0
6
+ # GNU General Public License version 2
7
+ # GNU Lesser General Public License version 2.1
8
+
9
+ require 'benchmark'
10
+
11
+ require File.expand_path('clamp', File.dirname(__FILE__))
12
+
13
+ Benchmark.measure do
14
+ clamp_a(10, 40, 90)
15
+ end
16
+
17
+ Benchmark.measure 'clamp_a1' do
18
+ clamp_a(10, 40, 90)
19
+ end
20
+
21
+ Benchmark.realtime do
22
+ clamp_a(10, 40, 90)
23
+ end
24
+
25
+ Benchmark.benchmark(Benchmark::CAPTION, 7, Benchmark::FORMAT, ">total:", ">avg:") do |x|
26
+ tf = x.report('clamp_a1') { clamp_a(10, 40, 90) }
27
+ tt = x.report('clamp_b1') { clamp_b(10, 40, 90) }
28
+ end
29
+
30
+ Benchmark.bm do |x|
31
+ x.report { clamp_a(10, 40, 90) }
32
+ x.report('clamp_a3') { clamp_a(10, 40, 90) }
33
+ x.report('clamp_b3') { clamp_b(10, 40, 90) }
34
+ end
35
+
36
+ Benchmark.bmbm do |x|
37
+ x.report { clamp_a(10, 40, 90) }
38
+ x.report('clamp_a4') { clamp_a(10, 40, 90) }
39
+ x.report('clamp_b4') { clamp_b(10, 40, 90) }
40
+ end
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
2
+ # code is released under a tri EPL/GPL/LGPL license. You can use it,
3
+ # redistribute it and/or modify it under the terms of the:
4
+ #
5
+ # Eclipse Public License version 1.0
6
+ # GNU General Public License version 2
7
+ # GNU Lesser General Public License version 2.1
8
+
9
+ require 'benchmark/ips'
10
+
11
+ require File.expand_path('clamp', File.dirname(__FILE__))
12
+
13
+ Benchmark.ips do |x|
14
+ x.config(:time => 5, :warmup => 2)
15
+
16
+ x.time = 5
17
+ x.warmup = 2
18
+
19
+ x.report { clamp_a(10, 40, 90) }
20
+ x.report('clamp_a1') { clamp_a(10, 40, 90) }
21
+ x.report('clamp_b1') { clamp_b(10, 40, 90) }
22
+
23
+ x.report('clamp_a2') do |times|
24
+ i = 0
25
+ while i < times
26
+ clamp_a(10, 40, 90)
27
+ i += 1
28
+ end
29
+ end
30
+
31
+ x.report('clamp_a3', 'clamp_a(10, 40, 90)')
32
+
33
+ x.compare!
34
+ end