bench_press 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +83 -0
- data/README.rdoc +2 -0
- data/VERSION +1 -1
- data/bench_press.gemspec +8 -4
- data/examples/clearing_an_array.rb +50 -0
- data/examples/foo.rb +12 -0
- data/lib/bench_press.rb +1 -1
- data/lib/bench_press/cli.rb +43 -1
- data/lib/bench_press/report.rb +6 -2
- data/lib/bench_press/runnable.rb +10 -3
- data/spec/bench_press/report_spec.rb +10 -4
- metadata +11 -7
- data/examples/array_vs_string_concatenation.rb +0 -30
data/README.markdown
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
Bench Press
|
2
|
+
===========
|
3
|
+
|
4
|
+
Bench Press is a simple dsl around Ruby's Benchmark library.
|
5
|
+
|
6
|
+
Place the code you wish to benchmark inside of a measure block, run the
|
7
|
+
bench_press command and you'll get a markdown report containing your system
|
8
|
+
information and the realtime benchmark.
|
9
|
+
|
10
|
+
Additionally, benchmarks can be published to the
|
11
|
+
[Ruby Benchmark](http://rubybenchmark.com) via
|
12
|
+
`bench_press --publish benchmark.rb` command.
|
13
|
+
|
14
|
+
### Creating a new benchmark
|
15
|
+
|
16
|
+
Use the `--new` flag to get started
|
17
|
+
$ bench_press --new benchmark
|
18
|
+
$ vi benchmark.rb
|
19
|
+
|
20
|
+
## Example
|
21
|
+
|
22
|
+
# foo.rb
|
23
|
+
require 'bench_press'
|
24
|
+
extend BenchPress
|
25
|
+
|
26
|
+
base_string = ""
|
27
|
+
measure "string append" do
|
28
|
+
base_string << "Hello World"
|
29
|
+
end
|
30
|
+
|
31
|
+
base_string = ""
|
32
|
+
measure "string +=" do
|
33
|
+
base_string += "Hello World"
|
34
|
+
end
|
35
|
+
|
36
|
+
$ bench_press foo.rb
|
37
|
+
|
38
|
+
Foo
|
39
|
+
===
|
40
|
+
Date: August 05, 2010
|
41
|
+
|
42
|
+
System Information
|
43
|
+
------------------
|
44
|
+
Operating System: Mac OS X 10.6.4 (10F569)
|
45
|
+
CPU: Intel Core 2 Duo 2.4 GHz
|
46
|
+
Processor Count: 2
|
47
|
+
Memory: 4 GB
|
48
|
+
ruby 1.8.7 (2009-12-24 patchlevel 248) [i686-darwin10.2.0], MBARI 0x6770, Ruby Enterprise Edition 2010.01
|
49
|
+
|
50
|
+
"string append" is up to 71% faster over 1000 repetitions
|
51
|
+
---------------------------------------------------------
|
52
|
+
|
53
|
+
string append 0.00270986557006836 secs Fastest
|
54
|
+
string += 0.00948691368103027 secs 71% Slower
|
55
|
+
|
56
|
+
## Details
|
57
|
+
The default number of repetitions is 1000 meaning each measure block is run
|
58
|
+
1000 times.
|
59
|
+
|
60
|
+
Each measure block is run in a forked subprocess in an attempt to isolate the
|
61
|
+
memory usage per measurement. As of 0.3.0, the benchmark is run twice, the
|
62
|
+
first run gets thrown away while the second run is added to the report.
|
63
|
+
|
64
|
+
## Running the binary/examples locally
|
65
|
+
I use rubygems but this library is $LOAD_PATH friendly which means we need to
|
66
|
+
set up our own load path when playing locally.
|
67
|
+
|
68
|
+
Try sourcing the .dev file
|
69
|
+
|
70
|
+
$ source .dev
|
71
|
+
|
72
|
+
## Note on Patches/Pull Requests
|
73
|
+
* Fork the project.
|
74
|
+
* Make your feature addition or bug fix.
|
75
|
+
* Add tests for it. This is important so I don't break it in a
|
76
|
+
future version unintentionally.
|
77
|
+
* Commit, do not mess with rakefile, version, or history.
|
78
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
79
|
+
* Send me a pull request. Bonus points for topic branches.
|
80
|
+
|
81
|
+
## Copyright
|
82
|
+
|
83
|
+
Copyright (c) 2009 Sandro Turriate. See LICENSE for details.
|
data/README.rdoc
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/bench_press.gemspec
CHANGED
@@ -5,17 +5,18 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bench_press}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Sandro Turriate"]
|
12
|
-
s.date = %q{2010-08-
|
12
|
+
s.date = %q{2010-08-05}
|
13
13
|
s.default_executable = %q{bench_press}
|
14
14
|
s.description = %q{Sharable benchmarks}
|
15
15
|
s.email = %q{sandro.turriate@gmail.com}
|
16
16
|
s.executables = ["bench_press"]
|
17
17
|
s.extra_rdoc_files = [
|
18
|
-
"README.
|
18
|
+
"README.markdown",
|
19
|
+
"README.rdoc",
|
19
20
|
"TODO"
|
20
21
|
]
|
21
22
|
s.files = [
|
@@ -25,11 +26,13 @@ Gem::Specification.new do |s|
|
|
25
26
|
".rvmrc",
|
26
27
|
"Gemfile",
|
27
28
|
"MIT-LICENSE",
|
29
|
+
"README.markdown",
|
28
30
|
"README.rdoc",
|
29
31
|
"Rakefile",
|
30
32
|
"VERSION",
|
31
33
|
"bench_press.gemspec",
|
32
34
|
"bin/bench_press",
|
35
|
+
"examples/clearing_an_array.rb",
|
33
36
|
"examples/compare_rr_to_rspec.rb",
|
34
37
|
"examples/existence_of_method.rb",
|
35
38
|
"examples/hash_merge.rb",
|
@@ -67,9 +70,10 @@ Gem::Specification.new do |s|
|
|
67
70
|
"spec/bench_press_spec.rb",
|
68
71
|
"spec/spec_helper.rb",
|
69
72
|
"spec/support/measurable.rb",
|
70
|
-
"examples/
|
73
|
+
"examples/clearing_an_array.rb",
|
71
74
|
"examples/compare_rr_to_rspec.rb",
|
72
75
|
"examples/existence_of_method.rb",
|
76
|
+
"examples/foo.rb",
|
73
77
|
"examples/hash_merge.rb",
|
74
78
|
"examples/implicit_versus_explicit_return.rb",
|
75
79
|
"examples/regexp_matching.rb",
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'bench_press'
|
2
|
+
|
3
|
+
extend BenchPress
|
4
|
+
|
5
|
+
author 'Sandro Turriate'
|
6
|
+
date '2010-08-01'
|
7
|
+
summary "
|
8
|
+
What's the best way to clear out an array? Could be useful if you're storing
|
9
|
+
messages in an array like a buffer. How should you flush the buffer when
|
10
|
+
you're done with it?
|
11
|
+
"
|
12
|
+
|
13
|
+
reps 10_000
|
14
|
+
|
15
|
+
ARRAY = (1..1000).to_a.freeze
|
16
|
+
|
17
|
+
measure "Array#clear" do
|
18
|
+
a = ARRAY.dup
|
19
|
+
a.clear
|
20
|
+
end
|
21
|
+
|
22
|
+
measure "Array#replace" do
|
23
|
+
a = ARRAY.dup
|
24
|
+
a.replace []
|
25
|
+
end
|
26
|
+
|
27
|
+
measure "Assign the variable to a new array" do
|
28
|
+
a = ARRAY.dup
|
29
|
+
a = []
|
30
|
+
end
|
31
|
+
|
32
|
+
measure "Array#-" do
|
33
|
+
a = ARRAY.dup
|
34
|
+
a = a - a
|
35
|
+
end
|
36
|
+
|
37
|
+
measure "Array#delete_if" do
|
38
|
+
a = ARRAY.dup
|
39
|
+
a.delete_if {true}
|
40
|
+
end
|
41
|
+
|
42
|
+
measure "Array#drop" do
|
43
|
+
a = ARRAY.dup
|
44
|
+
a = a.drop(a.size)
|
45
|
+
end
|
46
|
+
|
47
|
+
measure "Array#shift(n)" do
|
48
|
+
a = ARRAY.dup
|
49
|
+
a.shift(a.size)
|
50
|
+
end
|
data/examples/foo.rb
ADDED
data/lib/bench_press.rb
CHANGED
data/lib/bench_press/cli.rb
CHANGED
@@ -30,11 +30,15 @@ module BenchPress
|
|
30
30
|
@optparse ||= OptionParser.new do |opts|
|
31
31
|
opts.banner = "Usage: bench_press [options] file_to_benchmark.rb"
|
32
32
|
|
33
|
+
opts.on( '-n', '--new', 'Create a new benchmark' ) do
|
34
|
+
options[:new] = true
|
35
|
+
end
|
36
|
+
|
33
37
|
opts.on( '-p', '--publish', 'Publish the benchmark to http://rubybenchmark.com' ) do
|
34
38
|
options[:publish] = true
|
35
39
|
end
|
36
40
|
|
37
|
-
opts.on('--email EMAIL', String, "Author email, defaults to #{git_email}") do |email|
|
41
|
+
opts.on('--email EMAIL', String, "Author email used when publishing, defaults to #{git_email}") do |email|
|
38
42
|
options[:email] = email
|
39
43
|
end
|
40
44
|
|
@@ -49,6 +53,8 @@ module BenchPress
|
|
49
53
|
exit_with_version
|
50
54
|
elsif file_exists?
|
51
55
|
perform_bench_press
|
56
|
+
elsif options[:new]
|
57
|
+
new_bench_press
|
52
58
|
else
|
53
59
|
abort "Could not proceed, please supply the filename you wish to benchmark"
|
54
60
|
end
|
@@ -88,5 +94,41 @@ module BenchPress
|
|
88
94
|
abort "Email missing. Use bench_press --publish --email me@example.com file.rb"
|
89
95
|
end
|
90
96
|
end
|
97
|
+
|
98
|
+
def new_bench_press
|
99
|
+
if filename && File.exists?(file_path_with_rb)
|
100
|
+
abort "A file named #{filename} already exists"
|
101
|
+
else
|
102
|
+
File.open(file_path_with_rb, 'w') { |f| f.write(template) } unless file_exists?
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def file_path_with_rb
|
107
|
+
file_path + '.rb'
|
108
|
+
end
|
109
|
+
|
110
|
+
def template
|
111
|
+
<<-TEMPLATE
|
112
|
+
|
113
|
+
require 'bench_press'
|
114
|
+
|
115
|
+
extend BenchPress
|
116
|
+
|
117
|
+
name 'gem1 vs. gem2'
|
118
|
+
author 'YOUR NAME'
|
119
|
+
date '#{Time.now.strftime('%Y-%m-%d')}'
|
120
|
+
summary "
|
121
|
+
Describe what you're benchmarking
|
122
|
+
"
|
123
|
+
|
124
|
+
reps 10_000 #number of repetitions
|
125
|
+
|
126
|
+
measure "Class#method" do
|
127
|
+
# code to be benchmarked
|
128
|
+
end
|
129
|
+
|
130
|
+
TEMPLATE
|
131
|
+
end
|
132
|
+
|
91
133
|
end
|
92
134
|
end
|
data/lib/bench_press/report.rb
CHANGED
@@ -56,7 +56,7 @@ module BenchPress
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def heading
|
59
|
-
%("#{result.fastest.name}" is up to #{result.slowest.percent_slower}% faster over #{repetitions} repetitions)
|
59
|
+
%("#{result.fastest.name}" is up to #{result.slowest.percent_slower}% faster over #{formatted_number repetitions} repetitions)
|
60
60
|
end
|
61
61
|
|
62
62
|
def runnable_heading
|
@@ -103,7 +103,7 @@ module BenchPress
|
|
103
103
|
def repetitions
|
104
104
|
Runnable.repetitions
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
def row(*columns)
|
108
108
|
row = spacer
|
109
109
|
columns.each do |column|
|
@@ -115,6 +115,10 @@ module BenchPress
|
|
115
115
|
def spacer
|
116
116
|
' ' * SPACING
|
117
117
|
end
|
118
|
+
|
119
|
+
def formatted_number(number, delimiter = ',')
|
120
|
+
number.to_s.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
|
121
|
+
end
|
118
122
|
|
119
123
|
def run_name(content)
|
120
124
|
content.to_s.ljust(result.longest_name.size + SPACING)
|
data/lib/bench_press/runnable.rb
CHANGED
@@ -25,10 +25,9 @@ module BenchPress
|
|
25
25
|
def run
|
26
26
|
r,w = IO.pipe
|
27
27
|
fork do
|
28
|
+
run_it
|
28
29
|
time = Benchmark.realtime do
|
29
|
-
|
30
|
-
code_block.call(i)
|
31
|
-
end
|
30
|
+
run_it
|
32
31
|
end
|
33
32
|
w.write time
|
34
33
|
w.close_write
|
@@ -55,5 +54,13 @@ module BenchPress
|
|
55
54
|
:fastest => fastest
|
56
55
|
}
|
57
56
|
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def run_it
|
61
|
+
self.class.repetitions.times do |i|
|
62
|
+
code_block.call(i)
|
63
|
+
end
|
64
|
+
end
|
58
65
|
end
|
59
66
|
end
|
@@ -38,7 +38,13 @@ describe BenchPress::Report do
|
|
38
38
|
subject.date.should == custom_date
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
|
+
describe "#formatted_number" do
|
43
|
+
it "comma-separates a number" do
|
44
|
+
subject.send(:formatted_number, 1000000).should == "1,000,000"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
42
48
|
describe "#runnable_results" do
|
43
49
|
let(:report) do
|
44
50
|
r = BenchPress::Report.new
|
@@ -52,13 +58,13 @@ describe BenchPress::Report do
|
|
52
58
|
|
53
59
|
it "displays a heading" do
|
54
60
|
heading = <<-EOS
|
55
|
-
"Implicit return" is up to 17% faster over
|
56
|
-
|
61
|
+
"Implicit return" is up to 17% faster over 1,000 repetitions
|
62
|
+
------------------------------------------------------------
|
57
63
|
EOS
|
58
64
|
|
59
65
|
report.send(:runnable_heading).should == heading.strip
|
60
66
|
end
|
61
|
-
|
67
|
+
|
62
68
|
it "displays the table of results" do
|
63
69
|
table = <<-EOS
|
64
70
|
Implicit return 0.00029 secs Fastest
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bench_press
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sandro Turriate
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-08-
|
18
|
+
date: 2010-08-05 00:00:00 -04:00
|
19
19
|
default_executable: bench_press
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -105,6 +105,7 @@ executables:
|
|
105
105
|
extensions: []
|
106
106
|
|
107
107
|
extra_rdoc_files:
|
108
|
+
- README.markdown
|
108
109
|
- README.rdoc
|
109
110
|
- TODO
|
110
111
|
files:
|
@@ -114,11 +115,13 @@ files:
|
|
114
115
|
- .rvmrc
|
115
116
|
- Gemfile
|
116
117
|
- MIT-LICENSE
|
118
|
+
- README.markdown
|
117
119
|
- README.rdoc
|
118
120
|
- Rakefile
|
119
121
|
- VERSION
|
120
122
|
- bench_press.gemspec
|
121
123
|
- bin/bench_press
|
124
|
+
- examples/clearing_an_array.rb
|
122
125
|
- examples/compare_rr_to_rspec.rb
|
123
126
|
- examples/existence_of_method.rb
|
124
127
|
- examples/hash_merge.rb
|
@@ -142,7 +145,7 @@ files:
|
|
142
145
|
- spec/spec_helper.rb
|
143
146
|
- spec/support/measurable.rb
|
144
147
|
- TODO
|
145
|
-
- examples/
|
148
|
+
- examples/foo.rb
|
146
149
|
has_rdoc: true
|
147
150
|
homepage: http://github.com/sandro/bench_press
|
148
151
|
licenses: []
|
@@ -186,9 +189,10 @@ test_files:
|
|
186
189
|
- spec/bench_press_spec.rb
|
187
190
|
- spec/spec_helper.rb
|
188
191
|
- spec/support/measurable.rb
|
189
|
-
- examples/
|
192
|
+
- examples/clearing_an_array.rb
|
190
193
|
- examples/compare_rr_to_rspec.rb
|
191
194
|
- examples/existence_of_method.rb
|
195
|
+
- examples/foo.rb
|
192
196
|
- examples/hash_merge.rb
|
193
197
|
- examples/implicit_versus_explicit_return.rb
|
194
198
|
- examples/regexp_matching.rb
|
@@ -1,30 +0,0 @@
|
|
1
|
-
$:.unshift(File.dirname(__FILE__) + "/../lib")
|
2
|
-
require 'bench_press'
|
3
|
-
|
4
|
-
extend BenchPress
|
5
|
-
|
6
|
-
reps 100_000
|
7
|
-
array = []
|
8
|
-
measure "Array#<<" do |repetition|
|
9
|
-
array << "1234567890"
|
10
|
-
end
|
11
|
-
|
12
|
-
string = ""
|
13
|
-
measure "String#<<" do |repetition|
|
14
|
-
string << "1234567890"
|
15
|
-
end
|
16
|
-
|
17
|
-
a = (1..1000).to_a
|
18
|
-
measure "Array#clear" do
|
19
|
-
a.dup.clear
|
20
|
-
end
|
21
|
-
|
22
|
-
measure "Array#replace" do
|
23
|
-
a.dup
|
24
|
-
a.replace []
|
25
|
-
end
|
26
|
-
|
27
|
-
measure "Re-assigning to new array" do
|
28
|
-
a.dup
|
29
|
-
a = []
|
30
|
-
end
|