benchpress 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -4
- data/RELEASE.md +17 -0
- data/benchpress.gemspec +3 -3
- data/lib/benchpress/chart.rb +69 -26
- data/lib/benchpress/entity.rb +17 -4
- data/lib/benchpress/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38edc94e8271789d69bf667ddd3b7ee3f50694c4
|
4
|
+
data.tar.gz: 5c5814779e8c63a1c664216033945d21c2e914ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 166dd6357b3d57e2a803ae4c348d9482fd10e18f329da92ef025e5f14bfbd75ed0a6576903b6a053a9d8028d0b08fe0bea243bdb480379b3ce1f1081e78d90b8
|
7
|
+
data.tar.gz: 55c0ea8a9f44679627c9c8636dfb89fd7cd680fd57f662fc3848688372ba45e9e8efadd39b0566a0e10291be3b300aad70f90337a629e2c447e851377fd5d4d7
|
data/README.md
CHANGED
@@ -1,10 +1,36 @@
|
|
1
1
|
Benchpress
|
2
2
|
==========
|
3
3
|
|
4
|
-
Pit a few ruby methods against eachother, and chart it for great glory
|
5
|
-
|
6
|
-
Fair warning, this is super alpha one hour quick hack type material here. I intend to make it prettier later among other things, but I find it at least partially useful at this stage.
|
4
|
+
Pit a few ruby methods against eachother, and chart it for great glory.
|
7
5
|
|
8
6
|
Props to the folks at Gruff (https://github.com/topfunky/gruff) for making this simpler to do, and to the Ruby team behind Benchmark.
|
9
7
|
|
10
|
-
|
8
|
+
## How to Benchpress
|
9
|
+
|
10
|
+
We're going to need to define a chart.
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
c = Benchpress::Chart.new(
|
14
|
+
entities: {
|
15
|
+
string: -> { 'string' },
|
16
|
+
symbol: -> { :symbol }
|
17
|
+
},
|
18
|
+
min: 10_000, # Minimum times to run. Default: 0
|
19
|
+
max: 100_000, # Maximum times to run. Default: 1_000
|
20
|
+
step: 10_000, # Step rate for next benchmark. Default: 1
|
21
|
+
name: 'string_vs_symbol', # File name. Default: 'Time.now.strftime '%Y-%m-%d-%H:%M:%S''
|
22
|
+
format: 'png' # File format. Default: png
|
23
|
+
)
|
24
|
+
```
|
25
|
+
|
26
|
+
and then render it:
|
27
|
+
```ruby
|
28
|
+
c.render # Line chart
|
29
|
+
|
30
|
+
c.render :line # Line chart
|
31
|
+
c.render :bar # Bar chart
|
32
|
+
```
|
33
|
+
|
34
|
+
![](new pic url)
|
35
|
+
|
36
|
+
Voila! Instant chart with realtime benchmarks to demonstrate complexities of methods everywhere! Supports an arbitrary number of entities.
|
data/RELEASE.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# v0.0.1
|
2
|
+
|
3
|
+
Initial release
|
4
|
+
|
5
|
+
# v1.0.0
|
6
|
+
|
7
|
+
## Bug Fixes
|
8
|
+
|
9
|
+
* Data points accumulating between runs on same entities
|
10
|
+
|
11
|
+
## Changes
|
12
|
+
|
13
|
+
* Entities are no longer directly instantiated
|
14
|
+
* Entities are passed as a hash, in which the keys are the entities name, and the values are methods.
|
15
|
+
* Increase in rendering options
|
16
|
+
* Can now render bar charts.
|
17
|
+
* More efficient stepping algorithm, decreases runtime.
|
data/benchpress.gemspec
CHANGED
@@ -9,9 +9,9 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Brandon Weaver"]
|
10
10
|
spec.email = ["keystonelemur@gmail.com"]
|
11
11
|
spec.description = %q{Pit Ruby methods against eachother in benchmark, and chart for great glory}
|
12
|
-
spec.summary = %q{Ruby Benchmark + Gruff to auto-gen charts}
|
12
|
+
spec.summary = %q{Ruby Benchmark + Gruff to auto-gen charts for method profiline}
|
13
13
|
spec.homepage = "https://github.com/baweaver/Benchpress"
|
14
|
-
spec.license = "
|
14
|
+
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
@@ -20,5 +20,5 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
|
-
spec.
|
23
|
+
spec.add_runtime_dependency "gruff"
|
24
24
|
end
|
data/lib/benchpress/chart.rb
CHANGED
@@ -1,47 +1,90 @@
|
|
1
|
+
require 'pry'
|
2
|
+
|
1
3
|
module Benchpress
|
2
4
|
class Chart
|
3
|
-
|
4
|
-
#
|
5
|
-
# max
|
5
|
+
|
6
|
+
# format - format of the file
|
7
|
+
# max - maximum # of profiles to run
|
8
|
+
# min - minimum # of profiles to run
|
9
|
+
# name - name of the file
|
10
|
+
# step - increment rate
|
11
|
+
# theme - theme of the chart
|
6
12
|
# entities - data methods to run against
|
7
13
|
def initialize(opts = {})
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@
|
14
|
+
@format = opts[:format] || 'png'
|
15
|
+
@max = opts[:max] || 1000
|
16
|
+
@min = opts[:min] || 0
|
17
|
+
@name = opts[:name] || "#{Time.now.strftime '%Y-%m-%d-%H:%M:%S'}"
|
18
|
+
@step = opts[:step] || 1
|
19
|
+
@theme = opts[:theme] || Gruff::Themes::THIRTYSEVEN_SIGNALS
|
20
|
+
@entities = parse_entities opts[:entities]
|
21
|
+
end
|
22
|
+
|
23
|
+
# Lets you parse in entities by passing a hash in.
|
24
|
+
#
|
25
|
+
# Benchpress::Chart.new(
|
26
|
+
# entities: {
|
27
|
+
# string: -> { 'string' }
|
28
|
+
# symbol: -> { :symbol }
|
29
|
+
# }
|
30
|
+
# )
|
31
|
+
def parse_entities(entities)
|
32
|
+
raise 'Must have entities' unless entities
|
33
|
+
@entities = entities.each_pair.reduce([]) { |ary, (name, method)| ary << Entity.new(name => method) }
|
15
34
|
end
|
16
35
|
|
36
|
+
# file_name.ext
|
17
37
|
def image_name
|
18
38
|
@name + '.' + @format
|
19
39
|
end
|
20
40
|
|
41
|
+
# Calculates Step Points
|
42
|
+
#
|
43
|
+
# (min / step) will render 0 unless min is greater than the step rate, giving the floor of the range
|
44
|
+
# (max / step) will render the maximum amount of times step will fit in the max wholly
|
45
|
+
#
|
46
|
+
# Caveat - If the max % step != 0, it will not render to the max. This is intended behavior.
|
21
47
|
def step_points
|
22
|
-
|
48
|
+
raise 'Cannot have larger step than max' if @step > @max
|
49
|
+
@step_points ||= ((@min / @step)..(@max / @step)).reduce([]) { |steps, i| steps << @step * i }
|
23
50
|
end
|
24
51
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
entity.data_points << Benchmark.measure { n.times { entity.method.call } }.real
|
29
|
-
end
|
30
|
-
end
|
52
|
+
# Only grab labels for every other run, so as to space them out a bit more.
|
53
|
+
def even_labels
|
54
|
+
step_points.each_with_index.reduce({}) { |hash, (val, i)| i.odd? ? hash : hash.merge!({ i => val.to_s }) }
|
31
55
|
end
|
32
56
|
|
33
|
-
|
34
|
-
|
57
|
+
# Get labels for every point
|
58
|
+
def all_labels
|
59
|
+
step_points.each_with_index.reduce({}) { |hash, (val, index)| hash.merge!({ index => val.to_s }) }
|
60
|
+
end
|
35
61
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
62
|
+
# Render the entities data for the chart
|
63
|
+
def calculate_method_data_points
|
64
|
+
@entities.each { |entity| entity.render_data(step_points) }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Render dispatcher. Note to refactor a tinge later.
|
68
|
+
def render(type = :line)
|
69
|
+
calculate_method_data_points
|
70
|
+
|
71
|
+
create_chart_data_for(
|
72
|
+
case type
|
73
|
+
when :line then Gruff::Line.new
|
74
|
+
when :bar then Gruff::Bar.new
|
75
|
+
end
|
76
|
+
).write image_name
|
77
|
+
end
|
78
|
+
|
79
|
+
def create_chart_data_for(chart)
|
80
|
+
chart.tap { |g|
|
81
|
+
g.labels = all_labels
|
40
82
|
g.theme = @theme
|
41
|
-
|
42
|
-
g.x_axis_label = 'Times (n)'
|
83
|
+
g.x_axis_label = 'Times Run (n)'
|
43
84
|
g.y_axis_label = 'Length (seconds)'
|
44
|
-
|
85
|
+
|
86
|
+
@entities.each { |entity| g.data *entity.data }
|
87
|
+
}
|
45
88
|
end
|
46
89
|
end
|
47
90
|
end
|
data/lib/benchpress/entity.rb
CHANGED
@@ -3,12 +3,25 @@ module Benchpress
|
|
3
3
|
attr_reader :method, :name
|
4
4
|
attr_accessor :data_points
|
5
5
|
|
6
|
-
#
|
7
|
-
#
|
6
|
+
# Pass in the name of the entity as a symbol, and its method as a lambda
|
7
|
+
#
|
8
|
+
# Ex:
|
9
|
+
# Benchpress::Entity.new(string: -> { 'string' })
|
10
|
+
#
|
11
|
+
# Warning: Direct instantiation has been deprecated, read the
|
8
12
|
def initialize(opts = {})
|
9
|
-
|
10
|
-
@name
|
13
|
+
raise 'Invalid formatting! Use "name: -> { method }"' unless opts.keys.length == 1
|
14
|
+
@name, @method = *opts.flatten
|
11
15
|
@data_points = []
|
12
16
|
end
|
17
|
+
|
18
|
+
def render_data(step_points)
|
19
|
+
@data_points.clear
|
20
|
+
step_points.each { |n| @data_points << Benchmark.measure { n.times { @method.call } }.real }
|
21
|
+
end
|
22
|
+
|
23
|
+
def data
|
24
|
+
[@name.to_s, @data_points]
|
25
|
+
end
|
13
26
|
end
|
14
27
|
end
|
data/lib/benchpress/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: benchpress
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Weaver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -45,7 +45,7 @@ dependencies:
|
|
45
45
|
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
|
-
type: :
|
48
|
+
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
@@ -64,6 +64,7 @@ files:
|
|
64
64
|
- Gemfile
|
65
65
|
- LICENSE.txt
|
66
66
|
- README.md
|
67
|
+
- RELEASE.md
|
67
68
|
- Rakefile
|
68
69
|
- benchpress.gemspec
|
69
70
|
- lib/benchpress.rb
|
@@ -73,7 +74,7 @@ files:
|
|
73
74
|
- lib/benchpress/version.rb
|
74
75
|
homepage: https://github.com/baweaver/Benchpress
|
75
76
|
licenses:
|
76
|
-
-
|
77
|
+
- MIT
|
77
78
|
metadata: {}
|
78
79
|
post_install_message:
|
79
80
|
rdoc_options: []
|
@@ -94,5 +95,5 @@ rubyforge_project:
|
|
94
95
|
rubygems_version: 2.1.10
|
95
96
|
signing_key:
|
96
97
|
specification_version: 4
|
97
|
-
summary: Ruby Benchmark + Gruff to auto-gen charts
|
98
|
+
summary: Ruby Benchmark + Gruff to auto-gen charts for method profiline
|
98
99
|
test_files: []
|