herokubench 0.0.9 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb2da4a4361fae8687d6f1000bc956fa668f09ab
4
- data.tar.gz: 1468528eb35ebf73b7cb01cf16b0a19f9c7017a1
3
+ metadata.gz: 1991f6c51c9f3abcdd15975c79aaa8cad9ab970a
4
+ data.tar.gz: 125fa53e62a2ca9189dab4af4a64fcfd1ec6f3db
5
5
  SHA512:
6
- metadata.gz: fbad4b333c5c4e3704634f4cef8481b16928d92efd1f10ffd62b35aec857b581fa654cd4e78c1851555378e170e6f542966bb80593e9bd04b64fe35190e6822e
7
- data.tar.gz: 40dc3ab2b9b76868efacbd43ac1f7663fd4467c446ef91fb2cef612e02472d593eb56bdaa0a4ce44add5d86f12c5e95e9eaaff7565504169cfeb49a0ab2ec903
6
+ metadata.gz: 23b53138b1c1ec6ed1926ebb01194b41956ff1aeaab2c10b92cd4a0cc207d9becef7f7ebd6dc39f0222d7c677f663052d271ffc21a84f34b68d1450362579e3e
7
+ data.tar.gz: 76e4c1fae840664be549815e7ae54064bf77ef21e65d8c0d03cfc882e79682da55e26be75238131ac66d8e30dcde8fc9a1bf7a336418a62737d13548eab327c5
data/README.md CHANGED
@@ -8,29 +8,29 @@ A build server in the cloud, heavily inspired by Vulcan.
8
8
 
9
9
  ## Usage
10
10
 
11
- $ hb help
12
- ommands:
13
- hb ab URL # Run apache-bench, using a single, one-off Heroku dyno
14
- hb create APP_NAME # Create your personal bench-server on Heroku
15
- hb help [COMMAND] # Describe available commands or one specific command
16
- hb multi URL # Run apache-bench, using multiple one-off dynos
17
-
11
+ $ hbench help
12
+ commands:
13
+ hbench ab [options] [http[s]://]hostname[:port]/path # Run apache-bench using a single one-off dyno
14
+ hbench create APP_NAME # Create your personal bench-server on Heroku
15
+ hbench help [COMMAND] # Describe available commands or one specific command
16
+ hbench multi NUMBER [options] [http[s]://]hostname[:port]/path # Run apache-bench, using multiple one-off dynos
17
+ hbench update # Updates your remote bench server
18
+
18
19
  Options:
19
20
  [--verbose]
20
21
 
21
22
 
22
-
23
23
  ## Examples
24
24
 
25
25
  ### Create a Bench Server
26
- $ hb create hbench-david
26
+ $ hbench create hbench-david
27
27
  Creating hbench-david... done, stack is cedar
28
28
  http://hbench-david.herokuapp.com/ | git@heroku.com:hbench-david.git
29
29
  ...
30
30
 
31
31
  ### Bench
32
32
 
33
- $ hb http://nodejssimple.herokuapp.com/
33
+ $ hbench -c 100 -n 1000 http://nodejssimple.herokuapp.com/
34
34
  Running one-off dyno, please be patient
35
35
  Running `ab -c 1000 -n 10000 http://nodejssimple.herokuapp.com/` attached to terminal... up, run.4045
36
36
  This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
@@ -21,10 +21,9 @@ require 'herokubench/result'
21
21
  # This class is based upon Vulcan, and copies heavily.
22
22
 
23
23
  class HerokuBench::CLI < Thor
24
- class_option "verbose", :type => :boolean
24
+ class_option :verbose, :type => :boolean
25
25
  check_unknown_options! :except => [:ab, :multi]
26
26
  default_task :ab
27
- class_options["verbose"] = false if class_options["verbose"].nil?
28
27
  Heroku.user_agent = "heroku-gem/#{Heroku::VERSION} (#{RUBY_PLATFORM}) ruby/#{RUBY_VERSION}"
29
28
  Heroku::Command.load
30
29
 
@@ -45,87 +44,87 @@ class HerokuBench::CLI < Thor
45
44
  update
46
45
  end
47
46
 
48
-
49
- desc "ab [options] [http[s]://]hostname[:port]/path", "Run apache-bench using a single one-off dyno"
47
+ desc "ab [options] [http[s]://]hostname[:port]/path", "Run apache-bench automatically spreading over dynos as necessary"
50
48
  long_desc <<-LONGDESC
51
- 'hb ab' will run apache-bench, using a one-off dyno on Heroku in order
52
- to best benchmark the performance of your webservice.
49
+ 'hb ab' will run apache-bench, splitting the work between up between as many dynos as necessary, for a maximum of
50
+ 100 concurrent connections per dyno. The arguments are passed directly to ab.
53
51
 
54
52
  For more information, run `hb ab help`
55
53
 
56
- > $ hb ab -c 100 -n 1000 http://www.google.com
54
+ > $ hbench ab -c 100 -n 1000 http://www.google.com
57
55
  LONGDESC
58
56
 
59
57
  def ab(*args)
60
- puts config[:app]
61
- error "no app yet, please create first" unless config[:app]
62
- puts "Running one-off dyno, please be patient"
63
- Heroku::Command.run("run", ["ab #{args.join(' ')}", "--app", "#{config[:app]}"])
58
+ num_requests_index = args.index("-n") #hack to extract number of requests from the ab arguments.
59
+ concurrency_level_index = args.index("-c") #hack to extract number of requests from the ab arguments.
60
+ unless concurrency_level_index.nil? or num_requests_index.nil? then
61
+ num_requests = args[num_requests_index + 1].to_i
62
+ concurrency_level = args[concurrency_level_index + 1].to_i
63
+
64
+ num_dynos = (concurrency_level/100.0).ceil
65
+ num_dynos = 1 if num_dynos ==0
66
+
67
+ say "Inferred #{num_dynos} instances" if options[:verbose]
68
+ args[args.index("-n") + 1] = (num_requests / num_dynos).to_i
69
+ args[args.index("-c") + 1] = (concurrency_level / num_dynos).to_i
70
+ end
71
+ num_dynos ||= 1
72
+ multi(num_dynos, *args)
64
73
  end
65
74
 
66
-
67
- desc "multi NUMBER [options] [http[s]://]hostname[:port]/path", "Run apache-bench, using multiple one-off dynos"
75
+ desc "multi NUMDYNOS [options] [http[s]://]hostname[:port]/path", "Run apache-bench, using multiple one-off dynos"
68
76
  long_desc <<-LONGDESC
69
- 'hb multi' will run apache-bench, using multiple one-off dynos in order
77
+ 'hbench multi' will run apache-bench, using a specfied number of dynos in order
70
78
  to incrase the throughput of your benchmark.
71
79
 
72
80
  The arguments are identical to that of 'hb ab' with the addition
73
- of the 'NUMBER' argument, representing the number of one-off dynos
81
+ of the 'NUMDYNOS' argument, representing the number of one-off dynos
74
82
  to execute your benchmark on.
75
83
 
76
- > $ hb multi 5 http://www.google.com
84
+ > $ hbench multi 5 http://www.google.com
77
85
  LONGDESC
78
86
  def multi(dynos, *args)
79
87
  error "no app yet, create first" unless config[:app]
80
88
  error "Number of dynos must be an integer greater than 1" unless dynos.to_i >= 1
89
+
81
90
  begin
82
- num_requests = args[args.index("-n") + 1].to_i #hack to extract number of requests from the ab arguments.
91
+ say "Using #{config[:app]}" if options[:verbose]
92
+ say "Benching with #{dynos} dynos and arguments #{args}" if options[:verbose]
83
93
 
84
94
  bencher_path = File.expand_path("../bencher.rb",__FILE__)
95
+ num_dynos = dynos.to_i
85
96
 
86
- numdynos = dynos.to_i
87
- results = []
88
97
  running_procs = {}
89
- progesses = {}
90
98
  ab_command = "ab #{args.join(' ')}"
91
99
 
92
- p_bar = ProgressBar.create(:title=>'Benching',:total=>numdynos*num_requests, :smoothing => 0.6)
100
+ p_bar = ProgressBar.create(:title=>'Benching',:total=>1 + num_dynos*100)
101
+ summary_result = ApacheBenchSummaryResult.new
93
102
 
94
- numdynos.times do |n|
103
+ num_dynos.times do |n|
95
104
  t_file = Tempfile.new("hbench_out_#{n}")
96
105
  pid = spawn( "ruby #{bencher_path} \"#{ab_command} \" --app #{config[:app]}", :out=>t_file.path, :err=>null_dev)
106
+
97
107
  running_procs[pid] = t_file
98
- progesses[pid] = 0
99
- puts t_file.path
108
+ summary_result.add_result(ApacheBenchResult.new(t_file))
109
+ puts t_file.path if options[:verbose]
100
110
  end
101
111
 
102
112
 
103
113
  until running_procs.empty?
104
114
  begin
105
- complete_results = Timeout.timeout(1) do
115
+ complete_results = Timeout.timeout(0.5) do
106
116
  pid = Process.wait
107
- results.push running_procs.delete(pid)
108
- p_bar.progress += num_requests - progesses[pid]
109
- progesses[pid] = num_requests
117
+ running_procs.delete(pid)
110
118
  end
111
119
  rescue Timeout::Error
112
- running_procs.each do |pid, tfile|
113
- progress = get_progress(tfile)
114
- p_bar.progress += progress - progesses[pid]
115
- progesses[pid] = progress
116
- end
120
+ diff = summary_result.get_progress() - p_bar.progress
121
+ p_bar.progress+= diff
117
122
  end
118
123
  end
119
-
120
- summary_result = ApacheBenchSummaryResult.new
121
124
 
122
- puts results
123
- results.each do |tfile|
124
- summary_result.add_result(ApacheBenchResult.new(tfile))
125
- end
125
+ p_bar.finish
126
126
  summary_result.print()
127
127
 
128
-
129
128
  rescue Interrupt
130
129
  say "Exiting...Please be patient"
131
130
  kill_running_procs(running_procs)
@@ -133,71 +132,37 @@ class HerokuBench::CLI < Thor
133
132
  say "Done"
134
133
  rescue => exception
135
134
  say("HerokuBench ran into an unexpected exception. Please contact @wcdolphin",:red)
135
+
136
+ begin
137
+ kill_running_procs(running_procs)
138
+ kill_running_dynos()
139
+ rescue
140
+ end #squelch exceptions when killing procs
141
+
136
142
  say(exception,:red)
137
143
  puts exception.backtrace
138
144
  end
139
145
  end
140
146
 
141
- private
142
147
 
143
- # Attemptes to parse a value as a Float or integer, defaulting to the original
144
- # string if unsuccesful.
145
- def parse(v)
146
- ((float = Float(v)) && (float % 1.0 == 0) ? float.to_i : float) rescue v
147
- end
148
148
 
149
- # pretty much the opposite of parse. Returns a string of the best way
150
- # to represent a float, int or string value
151
- def serialize(v)
152
- ((float = v.round(1)) && (float % 1.0 == 0) ? float.to_i.to_s : float.to_s) rescue v.to_s
153
- end
154
-
155
- def get_progress(tfile)
156
- tfile.rewind
149
+ desc "update", "Updates your remote bench server"
150
+ def update
151
+ error "No app yet, create first" unless config[:app]
157
152
 
158
- progress = tfile.each_line.collect do |line|
159
- group = line.scan(/Completed (\d+) requests/)
160
- group = group.empty? ? 0 : group[0][0]
153
+ Dir.mktmpdir do |dir|
154
+ Dir.chdir(dir) do
155
+ system "git init -q"
156
+ system "git remote add origin git@github.com:wcdolphin/heroku-benchserver.git"
157
+ system "git remote add heroku git@#{heroku_git_domain}:#{config[:app]}.git"
158
+ pullres = capture { system "git pull --quiet origin master"}
159
+ pushres = capture { system "git push heroku master --quiet"}
160
+ end
161
161
  end
162
- progress = progress.last.to_i
163
162
  end
164
- # def summarize(results)
165
- # summary = {}
166
-
167
- # results.each do |result|
168
- # result.each do |type, hash|
169
- # summary[type] = {} if summary[type].nil?
170
- # hash.each do |k,v|
171
- # summary[type][k] = [0.0] * v.length if summary[type][k].nil?
172
- # v.each_index do |i|
173
- # if not @@summable_fields.index(k).nil?
174
- # summary[type][k][i] += v[i]
175
- # elsif not @@medianable_fields.index(k).nil?
176
- # summary[type][k][i] += v[i] / results.length.to_f
177
- # elsif not @@maxable_fields.index(k).nil?
178
- # summary[type][k][i] = [v[i], summary[type][k][i]].max
179
- # else
180
- # summary[type][k][i] = v[i]
181
- # end
182
- # end
183
- # end
184
- # end
185
- # end
186
-
187
- # say "\tCumulative results, summed across dynos"
188
- # say ""
189
- # summary[:generic_result].each{|k,v| say format(k+":",v, 25)}
190
-
191
- # say ""
192
- # say "\t Connection Times (ms), median across dynos"
193
- # say format("",["min", "mean", "[+/-sd]" ,"median","max"],15)
194
- # summary[:connection_times].each{|k,v| say format(k+":",v, 15)}
195
-
196
- # say ""
197
- # say "\t Percentage of the requests served within a certain time (ms)"
198
- # say "\t across dynos"
199
- # summary[:response_time_cdf].each{|k,v| say format(k+"",v, 15)}
200
- # end
163
+
164
+ private
165
+
201
166
 
202
167
  def kill_running_procs(running_procs)
203
168
  print "Killing running processes"
@@ -219,45 +184,6 @@ class HerokuBench::CLI < Thor
219
184
  end
220
185
  end
221
186
 
222
- def format(k,v, pad)
223
- "#{fill(k,pad)}#{v.map{|val| fill(serialize val)}.join('')}\r\n"
224
- end
225
-
226
- def fill(str, length=12)
227
- "#{str}#{" " * (length - str.length)}"
228
- end
229
-
230
- def get_result_hash(f)
231
- result_hash = {}
232
- f.each_line do |line|
233
- @@result_type.each do |k,v|
234
- group = line.scan(v)
235
- if not group.nil? and group.length.equal? 1
236
- capture = group[0].map {|v| parse v} #convert to float/int/etc
237
- result_hash[k] = {} unless result_hash.has_key?(k)
238
- res_key = capture[0]
239
- res_values = capture.slice(1, capture.length)
240
- result_hash[k][res_key] = res_values
241
- end
242
- end
243
- end
244
- result_hash
245
- end
246
-
247
- def update
248
- error "no app yet, create first" unless config[:app]
249
-
250
- Dir.mktmpdir do |dir|
251
- Dir.chdir(dir) do
252
- system "git init -q"
253
- system "git remote add origin git@github.com:wcdolphin/heroku-benchserver.git"
254
- system "git remote add heroku git@#{heroku_git_domain}:#{config[:app]}.git"
255
- pullres = capture { system "git pull --quiet origin master"}
256
- pushres = capture { system "git push heroku master --quiet"}
257
- end
258
- end
259
- end
260
-
261
187
  def capture
262
188
  results = $stdout = StringIO.new
263
189
  yield
@@ -19,110 +19,147 @@ require 'tempfile'
19
19
  require 'ruby-progressbar'
20
20
 
21
21
 
22
- class BaseResult
22
+ class BaseResult < Thor
23
23
  @@summable_fields = []
24
24
  @@maxable_fields = []
25
25
  end
26
26
 
27
27
  class ApacheBenchResult < BaseResult
28
- attr_accessor :result_hash
29
- @@result_regexes = {
30
- :connection_times=>/(.+):\s+\s+([\d|\.]+)\s+([\d|\.]+)\s+([\d|\.]+)\s+([\d|\.]+)\s+([\d|\.]+)/,
31
- :generic_result=> /^([\w\s]+):\s*([\d|\.]+)/,
32
- :response_time_cdf=>/(\d+%)\s+(\d+)/
33
- }
34
- @@summable_fields = ["Complete requests","Failed requests", "Write errors", "Requests per second", "Total transferred", "HTML transferred", "Concurrency Level"]
35
- @@averageable_fields = ["Connect", "Processing", "Waiting", "Total", "Time per request", "Time taken for tests"]
36
- @@maxable_fields = ["50%", "66%", "75%", "80%", "90%", "95%", "98%", "99%","100%"]
37
-
38
- def initialize(temp_file)
39
- @result_hash = {}
40
-
41
- temp_file.each_line do |line|
42
- @@result_regexes.each do |type,v|
43
- group = line.scan(v)
44
- if not group.nil? and group.length.equal? 1
45
- capture = group[0].map {|v| parse v} #convert to float/int/etc
46
- res_key = capture[0]
47
- res_values = capture.slice(1, capture.length)
48
-
49
- @result_hash[type] = {} unless @result_hash.has_key? type
50
- @result_hash[type][res_key] = res_values.length == 1 ? res_values[0] : res_values
51
- end
52
- end
53
- end
54
- puts @result_hash
55
- end
56
28
 
29
+ attr_accessor :result_tfile
30
+ @@result_regexes = {
31
+ :connection_times=>/(.+):\s+\s+([\d|\.]+)\s+([\d|\.]+)\s+([\d|\.]+)\s+([\d|\.]+)\s+([\d|\.]+)/,
32
+ :generic_result=> /^([\w\s]+):\s*([\d|\.]+)/,
33
+ :response_time_cdf=>/(\d+%)\s+(\d+)/
34
+ }
35
+ @@summable_fields = ["Complete requests","Failed requests", "Write errors", "Requests per second", "Total transferred", "HTML transferred", "Concurrency Level"]
36
+ @@averageable_fields = ["Connect", "Processing", "Waiting", "Total", "Time per request", "Time taken for tests"]
37
+ @@maxable_fields = ["50%", "66%", "75%", "80%", "90%", "95%", "98%", "99%","100%"]
38
+
39
+ no_commands do
40
+ def initialize(temp_file)
41
+ @result_tfile = temp_file
42
+ end
43
+
44
+ def result_hash()
45
+ @result_tfile.rewind
46
+ resulting_hash = {}
47
+ @result_tfile.each_line do |line|
48
+ @@result_regexes.each do |type,v|
49
+ group = line.scan(v)
50
+ if not group.nil? and group.length.equal? 1
51
+ capture = group[0].map {|v| parse v} #convert to float/int/etc
52
+ res_key = capture[0]
53
+ res_values = capture.slice(1, capture.length)
54
+
55
+ resulting_hash[type] = {} unless resulting_hash.has_key? type
56
+ resulting_hash[type][res_key] = res_values.length == 1 ? res_values.first : res_values
57
+ break
58
+ end
59
+ end
60
+ end
61
+ resulting_hash
62
+ end
63
+
64
+
65
+ # Returns the progress of this particular Dyno/Bench Result
66
+ def get_progress()
67
+ @result_tfile.rewind
68
+ progress = @result_tfile.each_line.collect do |line|
69
+ group = line.scan(/Completed (\d+) requests/)
70
+ group = group.empty? ? 0 : group[0][0]
71
+ end
72
+ progress.reject{|x| x == 0}.length * 10
73
+ end
74
+
75
+
76
+ def unlink()
77
+ @result_tfile.unlink
78
+ end
79
+ end
57
80
  end
58
81
 
59
82
  class ApacheBenchSummaryResult < ApacheBenchResult
83
+ no_commands do
84
+ def initialize()
85
+ @results = []
86
+ end
60
87
 
61
- def initialize()
62
- @results = []
63
- end
64
-
65
- def add_result(ab_result)
66
- @results.push ab_result
67
- end
88
+ def add_result(ab_result)
89
+ @results.push ab_result
90
+ end
68
91
 
69
- def get_summary_result()
70
- summary_result_hash = {}
92
+ def get_progress()
93
+ @results.collect{|r| r.get_progress}.inject(:+)
94
+ end
95
+
96
+ def unlink()
97
+ @results.each{|r| r.unlink}
98
+ end
99
+
100
+ def get_summary_result()
101
+ summary_result_hash = {}
102
+ @results.each do |result|
103
+ result.result_hash.each do |result_type, res_type_hashes|
104
+ summary_result_hash[result_type] = {} unless summary_result_hash.has_key? result_type
105
+ res_type_hashes.each do |result_key, value|
106
+ summary_result_hash[result_type][result_key] = [] unless summary_result_hash[result_type].has_key? result_key
107
+ summary_result_hash[result_type][result_key].push value
108
+ end
109
+ end
110
+ end
71
111
 
72
- @results.each do |result|
73
- result.result_hash.each do |result_type, res_type_hashes|
74
- summary_result_hash[result_type] = {} unless summary_result_hash.has_key? result_type
75
- res_type_hashes.each do |result_key, value|
76
- summary_result_hash[result_type][result_key] = [] unless summary_result_hash[result_type].has_key? result_key
77
- summary_result_hash[result_type][result_key].push value
112
+ summary_result_hash.each do |result_type, result_hash|
113
+ result_hash.each do |result_name, result_values|
114
+ if @@summable_fields.include? result_name
115
+ summary_result_hash[result_type][result_name] = result_values.inject(:+)
116
+ elsif @@averageable_fields.include? result_name
117
+ summary_result_hash[result_type][result_name] = deep_average(result_values)
118
+ elsif @@maxable_fields.include? result_name
119
+ summary_result_hash[result_type][result_name] = result_values.max
120
+ else
121
+ summary_result_hash[result_type][result_name] = result_values.first
122
+ end
78
123
  end
79
- end
124
+ end
125
+
126
+ summary_result_hash
80
127
  end
81
128
 
82
- summary_result_hash.each do |result_type, result_hash|
83
- result_hash.each do |result_name, result_values|
84
- if @@summable_fields.include? result_name
85
- summary_result_hash[result_type][result_name] = result_values.inject(:+)
86
- elsif @@averageable_fields.include? result_name
87
- summary_result_hash[result_type][result_name] = deep_average(result_values)
88
- elsif @@maxable_fields.include? result_name
89
- summary_result_hash[result_type][result_name] = result_values.max
90
- else
91
- summary_result_hash[result_type][result_name] = result_values.first
129
+ def print
130
+ summary = self.get_summary_result()
131
+ if summary.empty?
132
+ say("Herokubench ran into an error while executing ApacheBench. It is likely there was a syntax error in your command. Please see output below.", :red)
133
+ @results.first.result_tfile.rewind
134
+ @results.first.result_tfile.each_line do |line|
135
+ puts line
92
136
  end
137
+ return
138
+ end
139
+ say("Cumulative results, summed across dynos",:bold)
140
+ summary[:generic_result].each{|k,v| printf "%-20s %s\n", k + ":",v}
141
+
142
+ say ""
143
+ say("Connection Times (ms), median across dynos",:bold)
144
+ printf "%-20s %-8s %-8s %-8s %s\n", "","min", "mean", "[+/-sd]" ,"median","max"
145
+ summary[:connection_times].each do |k,v|
146
+ printf "%-20s %-8s %-8s %-8s %s\n",k +":", v[0], v[1], v[2], v[3], v[4], v[5]
93
147
  end
94
- end
95
148
 
96
- summary_result_hash
97
- end
98
- def print
99
- # puts "-----"
100
- summary = self.get_summary_result()
101
- # puts summary
102
- puts "-----"
103
- puts "\t Cumulative results, summed across dynos"
104
- puts ""
105
- summary[:generic_result].each{|k,v| printf "%-20s %s\n", k + ":",v}
106
-
107
- puts ""
108
- puts "\t Connection Times (ms), median across dynos"
109
- printf "%-20s %-6s %-6s %-6s %s\n", "","min", "mean", "[+/-sd]" ,"median","max"
110
- summary[:connection_times].each do |k,v|
111
- printf "%-20s %-6s %-6s %-6s %s\n",k +":", v[0], v[1], v[2], v[3], v[4], v[5]
149
+ if summary.has_key? :response_time_cdf #valid ab results can have no result CDF if there is only one response
150
+ say ""
151
+ say("Percentage of the requests served within a certain time (ms) across dynos", :bold)
152
+ summary[:response_time_cdf].each{|k,v| printf "\t%-20s %s\n", k,v}
153
+ end
112
154
  end
113
- puts ""
114
- puts "\t Percentage of the requests served within a certain time (ms)"
115
- puts "\t across dynos"
116
- summary[:response_time_cdf].each{|k,v| printf " %-20s %s\n", k,v}
117
-
118
155
  end
119
-
120
156
  end
121
157
 
122
158
 
123
159
 
124
160
  private
125
-
161
+ # Parses a value as a Float or integer, defaulting to the original
162
+ # string if unsuccesful.
126
163
  def parse(v)
127
164
  ((float = Float(v)) && (float % 1.0 == 0) ? float.to_i : float) rescue v
128
165
  end
@@ -131,13 +168,10 @@ def deep_average(arr)
131
168
  result = []
132
169
  if not arr.empty? and arr[0].is_a? Array #we need to do a 'deep' average.
133
170
  arr[0].each_index do |i|
134
- result[i] = arr.collect {|a| a[i]/arr.length.to_f}.inject(:+)
171
+ result[i] = arr.collect {|a| a[i]/arr.length.to_f}.inject(:+).round(1)
135
172
  end
136
173
  result
137
174
  else
138
- arr.collect {|a| a/arr.length}.inject(:+)
175
+ arr.collect {|a| a/arr.length}.inject(:+).round(1)
139
176
  end
140
177
  end
141
-
142
-
143
-
@@ -1,5 +1,5 @@
1
1
  module HerokuBench
2
2
 
3
- VERSION = "0.0.9"
3
+ VERSION = "1.0.0"
4
4
 
5
5
  end
data/spec/cli_spec.rb ADDED
@@ -0,0 +1,7 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+
3
+ require 'herokubench/result'
4
+
5
+ describe HerokuBench::CLI do
6
+
7
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: herokubench
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cory Dolphin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-11 00:00:00.000000000 Z
11
+ date: 2013-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: heroku
@@ -82,6 +82,7 @@ files:
82
82
  - lib/herokubench/version.rb
83
83
  - lib/herokubench.rb
84
84
  - README.md
85
+ - spec/cli_spec.rb
85
86
  homepage: https://github.com/wcdolphin/heroku-bench
86
87
  licenses:
87
88
  - MIT
@@ -102,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
103
  version: '0'
103
104
  requirements: []
104
105
  rubyforge_project:
105
- rubygems_version: 2.0.3
106
+ rubygems_version: 2.0.6
106
107
  signing_key:
107
108
  specification_version: 4
108
109
  summary: A gem to help load testing web applications deployed on AWS or Heroku, using