README.md in benchmark_driver-0.3.0 vs README.md in benchmark_driver-0.4.0
- old
+ new
@@ -1,171 +1,179 @@
# Benchmark::Driver [![Build Status](https://travis-ci.org/k0kubun/benchmark_driver.svg?branch=master)](https://travis-ci.org/k0kubun/benchmark_driver)
-Benchmark driver for different Ruby executables
+Fully-featured accurate benchmark driver for Ruby
-## Installation
+## Project Status
- $ gem install benchmark_driver
+**Under Construction**
-## Usage
+## Features
+NOTE: Pending ones are ~slashed~.
-```
-$ benchmark-driver -h
-Usage: benchmark-driver [options] [YAML]
- -e, --executables [EXECS] Ruby executables (e1::path1; e2::path2; e3::path3;...)
- -i, --ips [SECONDS] Measure IPS in duration seconds (default: 1)
- -l, --loop-count [COUNT] Measure execution time with loop count (default: 100000)
- -v, --verbose
-```
+### Accurate Measurement
-### Running single script
+- Low overhead benchmark by running generated script instead of calling Proc
+- Running multiple times to minimize measurement errors
+- Profiling memory, high-precision real time, ~user time and system time~
-With following `example_single.yml`,
+### Pluggable & Fully Featured
-```yml
-prelude: |
- require 'erb'
- erb = ERB.new(%q[Hello <%= 'World' %>])
-benchmark: erb.result
-```
+- Flexible and real-time output format in ips, execution time, ~markdown table~, etc.
+- Runner and output are all pluggable
+- ~Integrated benchmark support using external libraries~
-you can benchmark the script with multiple ruby executables.
+### Flexible Interface
-```
-$ benchmark-driver benchmarks/example_single.yml -e ruby1::ruby -e ruby2::ruby
-benchmark results:
-Execution time (sec)
-name ruby1 ruby2
-example_single 0.958 0.972
+- Ruby interface similar to benchmark stdlib, benchmark-ips
+- YAML input to easily manage structured benchmark set
+- Comparing multiple Ruby binaries, even with miniruby
-Speedup ratio: compare with the result of `ruby1' (greater is better)
-name ruby2
-example_single 0.986
+## Installation
+
```
+$ gem install benchmark_driver
+```
-And you can change benchmark output to IPS (iteration per second) by `-i` option.
+## Usage
-```
-$ benchmark-driver benchmarks/example_single.yml -e ruby1::ruby -e ruby2::ruby -i
-Result -------------------------------------------
- ruby1 ruby2
- example_single 99414.1 i/s 99723.3 i/s
+### Ruby Interface: Compatible Mode
-Comparison: example_single
- ruby2: 99723.3 i/s
- ruby1: 99414.1 i/s - 1.00x slower
+This interface is compatible with `Benchmark.bm` and `Benchmark.ips`, so it's good for migration.
+
+```rb
+require 'benchmark/driver'
+require 'active_support/all'
+array = []
+
+Benchmark.driver do |x|
+ x.report('blank?') { array.blank? }
+ x.report('empty?') { array.empty? }
+ x.compare!
+end
```
-### Running multiple scripts
+### Ruby Interface: Low Overhead Mode
-One YAML file can contain multiple benchmark scripts.
-With following `example_multi.yml`,
+This interface generates code to profile with low overhead and executes it.
-```yml
-prelude: |
- a = 'a' * 100
- b = 'b' * 100
-benchmarks:
- - name: join
- benchmark: |
- [a, b].join
- - name: interpolation
- benchmark: |
- "#{a}#{b}"
-```
+```rb
+require 'benchmark/driver'
-you can benchmark the scripts with multiple ruby executables.
+Benchmark.driver do |x|
+ x.prelude = <<~RUBY
+ require 'active_support/all'
+ array = []
+ RUBY
+ x.report('blank?', script: 'array.blank?')
+ x.report('empty?', script: 'array.empty?')
+end
```
-$ benchmark-driver benchmarks/example_multi.yml -e ruby1::ruby -e ruby2::ruby
-benchmark results:
-Execution time (sec)
-name ruby1 ruby2
-join 0.022 0.022
-interpolation 0.026 0.026
-Speedup ratio: compare with the result of `ruby1' (greater is better)
-name ruby2
-join 1.045
-interpolation 1.002
-```
+or simply:
-```
-$ benchmark-driver benchmarks/example_multi.yml -e ruby1::ruby -e ruby2::ruby -i
-Result -------------------------------------------
- ruby1 ruby2
- join 4701954.3 i/s 4639520.3 i/s
- interpolation 4263170.0 i/s 4044083.0 i/s
+```rb
+require 'benchmark/driver'
-Comparison: join
- ruby1: 4701954.3 i/s
- ruby2: 4639520.3 i/s - 1.01x slower
+Benchmark.driver do |x|
+ x.prelude = <<~RUBY
+ require 'active_support/all'
+ array = []
+ RUBY
-Comparison: interpolation
- ruby1: 4263170.0 i/s
- ruby2: 4044083.0 i/s - 1.05x slower
+ x.report(script: 'array.blank?')
+ x.report(script: 'array.empty?')
+end
```
-### Configuring modes
+### Structured YAML Input
-There are 2 modes:
+With `benchmark-driver` command, you can describe benchmark with YAML input.
-- Loop count: Enabled by `-l`. Optionally you can change count to loop by `-l COUNT`.
-- IPS: Enabled by `-i`. Optionally you can change duration by `-i DURATION`.
+```
+$ benchmark-driver -h
+Usage: benchmark-driver [options] [YAML]
+ -e, --executables [EXECS] Ruby executables (e1::path1; e2::path2; e3::path3;...)
+ --rbenv [VERSIONS] Ruby executables in rbenv (2.3.5;2.4.2;...)
+ -c, --compare Compare results (currently only supported in ips output)
+ -r, --repeat-count [NUM] Try benchmark NUM times and use the fastest result
+```
-Specifying both `-l` and `-i` is nonsense.
+#### Running single script
-### YAML syntax
-You can specify `benchmark:` or `benchmarks:`.
+With following `example_single.yml`,
-#### Single
```yml
-name: String # optional (default: file name)
-prelude: String # optional
-loop_count: Integer # optional
-benchmark: String # required
+prelude: |
+ require 'erb'
+ erb = ERB.new(%q[Hello <%= 'World' %>])
+benchmark: erb.result
```
-#### Multi
+you can benchmark the script with multiple ruby executables.
-```yml
-prelude: String # optional (shared)
-loop_count: Integer # optional (shared)
-benchmarks:
- - name: String # required
- prelude: String # optional (benchmark specific)
- loop_count: Integer # optional (benchmark specific)
- benchmark: String # required
```
+$ exe/benchmark-driver examples/yaml/example_single.yml --rbenv '2.4.2;trunk' --compare
+Warming up --------------------------------------
+ erb.result 10.973k i/100ms
+Calculating -------------------------------------
+ 2.4.2 trunk
+ erb.result 109.268k 123.611k i/s - 548.675k in 4.017080s 4.438720s
-### Debugging
+Comparison:
+ erb.result (trunk): 123611.1 i/s
+ erb.result (2.4.2): 109268.4 i/s - 1.13x slower
+```
-If you have a trouble like an unexpectedly fast result, you should check benchmark script by `-v`.
+#### Running multiple scripts
+One YAML file can contain multiple benchmark scripts.
+With following `example_multi.yml`,
+
+```yml
+prelude: |
+ a = 'a' * 100
+ b = 'b' * 100
+benchmark:
+ join: '[a, b].join'
+ str-interp: '"#{a}#{b}"'
```
-$ benchmark-driver benchmarks/example_multi.yml -v
---- Running "join" with "ruby" 957780 times ---
-a = 'a' * 100
-b = 'b' * 100
+you can benchmark the scripts with multiple ruby executables.
-i = 0
-while i < 957780
- i += 1
-[a, b].join
+```
+$ exe/benchmark-driver examples/yaml/example_multi.yml --rbenv '2.4.2;trunk' --compare
+Warming up --------------------------------------
+ join 515.787k i/100ms
+ str-interp 438.646k i/100ms
+Calculating -------------------------------------
+ 2.4.2 trunk
+ join 5.200M 4.740M i/s - 20.631M in 3.967750s 4.352565s
+ str-interp 4.306M 6.034M i/s - 21.932M in 4.075159s 3.634986s
-end
+Comparison:
+ str-interp (trunk): 6033674.6 i/s
+ join (2.4.2): 5199794.6 i/s - 1.16x slower
+ join (trunk): 4740075.1 i/s - 1.27x slower
+ str-interp (2.4.2): 4305563.1 i/s - 1.40x slower
```
## TODO
+### Runner
+- [x] Call
+- [x] Exec
+- [ ] Eval
-- Measure multiple times and use minimum result
-- Retry and reject negative result in ips mode
-- Change not to take long time for iteration count estimation in ips mode
+### Output
+- [x] IPS
+- [x] Time
+- [ ] CPU/System/Real Time
+- [ ] Memory
+- [ ] Markdown Table
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/k0kubun/benchmark_driver.
## License
-The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
+The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).