benchmark-interface 0.1

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