benchmark-http 0.2.0 → 0.3.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
  SHA256:
3
- metadata.gz: a7198efc6883b1ab033fabd79461782dc4a283d7a8643b962f13fc6ec9d8b630
4
- data.tar.gz: ae74b4d5cfb6d5407c600d46af92817897556fdd246b68591c23b3d40b3a8602
3
+ metadata.gz: de65883bfb494a1d1da97429666bd4a590361632cc008d1292e11003a00a8acc
4
+ data.tar.gz: 2b0a8c9f5d9d59799203e6030669a576c4802d0d95c1c1dd4dcf23bba7a875ce
5
5
  SHA512:
6
- metadata.gz: d930b61aec7683e5162fb0b6f4776b960562473506c574162861eefe91d07d898b3aa9efa755ee5e8464938d358efb34f2f0198dc8bb05907578109e6c7bae19
7
- data.tar.gz: 176349eac7a9b287dd60f85f1d2c97c78a3580cd6ec235533b4f81380e2060e82ace5c3bfa3fc9fed322d8d26e9f0f6e0876d9362a7930caeca52c1163b28171
6
+ metadata.gz: '039a873b982321ada9fcfd8cb3f848e46df8786ee2590a075a68580ad4aa5b3bcee638eb47f28a24e88faabf1349215193a02b65d25f377abe3ad091a36f594f'
7
+ data.tar.gz: 584cea3731b38082c4a1fb078d883c7eb8d61edc5b626d0ef5dc0ead41e9fe5338edbcfc6535f6b9a66e9187580fbcd25b73d68336e76502a3c5f8bb9a6b6e72
@@ -8,9 +8,9 @@ before_script:
8
8
 
9
9
  matrix:
10
10
  include:
11
- - rvm: 2.3
12
11
  - rvm: 2.4
13
12
  - rvm: 2.5
13
+ - rvm: 2.6
14
14
  - rvm: jruby-head
15
15
  env: JRUBY_OPTS="--debug -X+O"
16
16
  - rvm: ruby-head
data/Gemfile CHANGED
@@ -1,6 +1,7 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
-
5
- # Specify your gem's dependencies in benchmark-http.gemspec
6
3
  gemspec
4
+
5
+ group :development do
6
+ gem 'pry'
7
+ end
data/README.md CHANGED
@@ -20,6 +20,85 @@ Install it yourself:
20
20
 
21
21
  You can run `benchmark-http` is a top level tool for invoking specific benchmarks.
22
22
 
23
+ ### Spider
24
+
25
+ This benchmark spiders a website and generates some statistics on general access time.
26
+
27
+ ```shell
28
+ $ benchmark-http spider https://www.oriontransfer.co.nz/welcome/index
29
+ HEAD https://www.oriontransfer.co.nz/welcome/index -> HTTP/2.0 404 (unspecified bytes)
30
+ GET https://www.oriontransfer.co.nz/welcome/index (depth = 10)
31
+ GET https://www.oriontransfer.co.nz/welcome/index -> HTTP/2.0 404 (2263 bytes)
32
+ HEAD https://www.oriontransfer.co.nz/products/index -> HTTP/2.0 200 (unspecified bytes)
33
+ GET https://www.oriontransfer.co.nz/products/index (depth = 9)
34
+ HEAD https://www.oriontransfer.co.nz/services/index -> HTTP/2.0 200 (unspecified bytes)
35
+ GET https://www.oriontransfer.co.nz/services/index (depth = 9)
36
+ HEAD https://www.oriontransfer.co.nz/support/index -> HTTP/2.0 200 (unspecified bytes)
37
+ GET https://www.oriontransfer.co.nz/support/index (depth = 9)
38
+ HEAD https://www.oriontransfer.co.nz/support/contact-us -> HTTP/2.0 307 (unspecified bytes)
39
+ Following redirect to https://www.oriontransfer.co.nz/support/contact-us/index...
40
+ HEAD https://www.oriontransfer.co.nz/support/terms-of-service -> HTTP/2.0 200 (unspecified bytes)
41
+ GET https://www.oriontransfer.co.nz/support/terms-of-service (depth = 9)
42
+ GET https://www.oriontransfer.co.nz/products/index -> HTTP/2.0 200 (3469 bytes)
43
+ GET https://www.oriontransfer.co.nz/services/index -> HTTP/2.0 200 (2488 bytes)
44
+ GET https://www.oriontransfer.co.nz/support/index -> HTTP/2.0 200 (2246 bytes)
45
+ HEAD https://www.oriontransfer.co.nz/support/contact-us/index -> HTTP/2.0 200 (unspecified bytes)
46
+ GET https://www.oriontransfer.co.nz/support/contact-us/index (depth = 8)
47
+ GET https://www.oriontransfer.co.nz/support/terms-of-service -> HTTP/2.0 200 (8466 bytes)
48
+ HEAD https://www.oriontransfer.co.nz/products/library-inspector/index -> HTTP/2.0 200 (unspecified bytes)
49
+ GET https://www.oriontransfer.co.nz/products/library-inspector/index (depth = 8)
50
+ HEAD https://www.oriontransfer.co.nz/products/truth-tables/index -> HTTP/2.0 200 (unspecified bytes)
51
+ GET https://www.oriontransfer.co.nz/products/truth-tables/index (depth = 8)
52
+ HEAD https://www.oriontransfer.co.nz/products/fingerprint/index -> HTTP/2.0 200 (unspecified bytes)
53
+ GET https://www.oriontransfer.co.nz/products/fingerprint/index (depth = 8)
54
+ HEAD https://www.oriontransfer.co.nz/services/internet-services -> HTTP/2.0 200 (unspecified bytes)
55
+ GET https://www.oriontransfer.co.nz/services/internet-services (depth = 8)
56
+ HEAD https://www.oriontransfer.co.nz/services/software-development -> HTTP/2.0 200 (unspecified bytes)
57
+ GET https://www.oriontransfer.co.nz/services/software-development (depth = 8)
58
+ HEAD https://www.oriontransfer.co.nz/services/systems-administration -> HTTP/2.0 200 (unspecified bytes)
59
+ GET https://www.oriontransfer.co.nz/services/systems-administration (depth = 8)
60
+ HEAD https://www.oriontransfer.co.nz/services/website-development -> HTTP/2.0 200 (unspecified bytes)
61
+ GET https://www.oriontransfer.co.nz/services/website-development (depth = 8)
62
+ HEAD https://www.oriontransfer.co.nz/support/contact-us/ -> HTTP/2.0 307 (unspecified bytes)
63
+ Following redirect to https://www.oriontransfer.co.nz/support/contact-us/index...
64
+ GET https://www.oriontransfer.co.nz/support/contact-us/index -> HTTP/2.0 200 (3094 bytes)
65
+ GET https://www.oriontransfer.co.nz/products/library-inspector/index -> HTTP/2.0 200 (5592 bytes)
66
+ GET https://www.oriontransfer.co.nz/products/truth-tables/index -> HTTP/2.0 200 (4160 bytes)
67
+ GET https://www.oriontransfer.co.nz/products/fingerprint/index -> HTTP/2.0 200 (4414 bytes)
68
+ GET https://www.oriontransfer.co.nz/services/internet-services -> HTTP/2.0 200 (3362 bytes)
69
+ GET https://www.oriontransfer.co.nz/services/software-development -> HTTP/2.0 200 (3521 bytes)
70
+ GET https://www.oriontransfer.co.nz/services/systems-administration -> HTTP/2.0 200 (2979 bytes)
71
+ GET https://www.oriontransfer.co.nz/services/website-development -> HTTP/2.0 200 (3943 bytes)
72
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/library-inspector/_screenshots/large/Library%20Inspector%20(Libraries).png -> HTTP/2.0 200 (unspecified bytes)
73
+ Unsupported content type: image/png
74
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/library-inspector/_screenshots/large/Library%20Inspector%20(Libraries%20Disassembly).png -> HTTP/2.0 200 (unspecified bytes)
75
+ Unsupported content type: image/png
76
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/library-inspector/_screenshots/large/Library%20Inspector%20(Libraries%20QuickLook).png -> HTTP/2.0 200 (unspecified bytes)
77
+ Unsupported content type: image/png
78
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/library-inspector/_screenshots/large/Library%20Inspector%20(App).png -> HTTP/2.0 200 (unspecified bytes)
79
+ Unsupported content type: image/png
80
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/library-inspector/_screenshots/large/Library%20Inspector%20(App%20Headers).png -> HTTP/2.0 200 (unspecified bytes)
81
+ Unsupported content type: image/png
82
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/truth-tables/_screenshots/large/Reformat%20Expression.png -> HTTP/2.0 200 (unspecified bytes)
83
+ Unsupported content type: image/png
84
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/truth-tables/_screenshots/large/Large%20Tables.png -> HTTP/2.0 200 (unspecified bytes)
85
+ Unsupported content type: image/png
86
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/truth-tables/_screenshots/large/Tutor.png -> HTTP/2.0 200 (unspecified bytes)
87
+ Unsupported content type: image/png
88
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/truth-tables/_screenshots/large/Informative%20Text.png -> HTTP/2.0 200 (unspecified bytes)
89
+ Unsupported content type: image/png
90
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/fingerprint/_screenshots/large/Fingerprint%20(3).png -> HTTP/2.0 200 (unspecified bytes)
91
+ Unsupported content type: image/png
92
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/fingerprint/_screenshots/large/Fingerprint%20(2).png -> HTTP/2.0 200 (unspecified bytes)
93
+ Unsupported content type: image/png
94
+ HEAD https://www.oriontransfer.co.nz/_gallery/products/fingerprint/_screenshots/large/Fingerprint%20(1).png -> HTTP/2.0 200 (unspecified bytes)
95
+ Unsupported content type: image/png
96
+ HEAD https://www.oriontransfer.co.nz/services/training -> HTTP/2.0 200 (unspecified bytes)
97
+ GET https://www.oriontransfer.co.nz/services/training (depth = 7)
98
+ GET https://www.oriontransfer.co.nz/services/training -> HTTP/2.0 200 (2994 bytes)
99
+ 14 samples: 13x 200; 1x 404. 15.124294695167547 requests per second. S/D: 35.69ms.
100
+ ```
101
+
23
102
  ### Concurrency
24
103
 
25
104
  This benchmark determines the optimal level of concurrency (maximise throughput while keeping latency to a minimum).
@@ -16,7 +16,10 @@ Gem::Specification.new do |spec|
16
16
  spec.require_paths = ["lib"]
17
17
 
18
18
  spec.add_dependency("async-io", "~> 1.5")
19
- spec.add_dependency("async-http", "~> 0.9")
19
+ spec.add_dependency("async-http", "~> 0.27.0")
20
+ spec.add_dependency("async-await")
21
+
22
+ spec.add_dependency("trenni-sanitize")
20
23
 
21
24
  spec.add_dependency('samovar', "~> 1.3")
22
25
 
@@ -19,6 +19,8 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require_relative 'command/concurrency'
22
+ require_relative 'command/spider'
23
+
22
24
  require_relative 'version'
23
25
  require 'samovar'
24
26
 
@@ -39,7 +41,8 @@ module Benchmark
39
41
  end
40
42
 
41
43
  nested '<command>',
42
- 'concurrency' => Concurrency
44
+ 'concurrency' => Concurrency,
45
+ 'spider' => Spider
43
46
 
44
47
  def verbose?
45
48
  @options[:logging] == :verbose
@@ -0,0 +1,150 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative '../seconds'
22
+ require_relative '../statistics'
23
+ require_relative '../links_filter'
24
+
25
+ require 'async'
26
+ require 'async/http/client'
27
+ require 'async/http/url_endpoint'
28
+ require 'async/await'
29
+
30
+ require 'samovar'
31
+ require 'uri'
32
+
33
+ module Benchmark
34
+ module HTTP
35
+ module Command
36
+ class Spider < Samovar::Command
37
+ include Async::Await
38
+
39
+ self.description = "Spider a website and report on performance."
40
+
41
+ options do
42
+ option '-d/--depth <count>', "The number of nested URLs to traverse.", default: 10, type: Integer
43
+ option '-h/--headers', "Print out the response headers", default: false
44
+ end
45
+
46
+ many :urls, "One or more hosts to benchmark"
47
+
48
+ def log(method, url, response)
49
+ puts "#{method} #{url} -> #{response.version} #{response.status} (#{response.body&.length || 'unspecified'} bytes)"
50
+
51
+ response.headers.each do |key, value|
52
+ puts "\t#{key}: #{value}"
53
+ end if @options[:headers]
54
+ end
55
+
56
+ def extract_links(url, response)
57
+ base = url
58
+
59
+ body = response.read
60
+
61
+ begin
62
+ filter = LinksFilter.parse(body)
63
+ rescue
64
+ Async.logger.error($!)
65
+ return []
66
+ end
67
+
68
+ if filter.base
69
+ base = base + filter.base
70
+ end
71
+
72
+ filter.links.collect do |href|
73
+ begin
74
+ full_url = base + href
75
+
76
+ if full_url.host == url.host && full_url.kind_of?(URI::HTTP)
77
+ yield full_url
78
+ end
79
+ rescue ArgumentError, URI::InvalidURIError
80
+ puts "Could not fetch #{href}, relative to #{base}."
81
+ end
82
+ end.compact
83
+ end
84
+
85
+ async def fetch(statistics, client, url, depth = @options[:depth], fetched = Set.new)
86
+ return if fetched.include?(url) or depth == 0
87
+
88
+ fetched << url
89
+
90
+ request_uri = url.request_uri
91
+
92
+ response = timeout(10) do
93
+ client.head(request_uri)
94
+ end
95
+
96
+ log("HEAD", url, response)
97
+
98
+ if response.redirection?
99
+ location = url + response.headers['location']
100
+ if location.host == url.host
101
+ puts "Following redirect to #{location}..."
102
+ return fetch(statistics, client, location, depth-1, fetched).wait
103
+ else
104
+ puts "Ignoring redirect to #{location}."
105
+ return
106
+ end
107
+ end
108
+
109
+ content_type = response.headers['content-type']
110
+ unless content_type&.start_with? 'text/html'
111
+ puts "Unsupported content type: #{content_type}"
112
+ return
113
+ end
114
+
115
+ response = timeout(20) do
116
+ statistics.measure do
117
+ client.get(request_uri)
118
+ end
119
+ end
120
+
121
+ log("GET", url, response)
122
+
123
+ extract_links(url, response) do |href|
124
+ fetch(statistics, client, href, depth - 1, fetched)
125
+ end.each(&:wait)
126
+ rescue Async::TimeoutError
127
+ Async.logger.error("Timeout while fetching #{url}")
128
+ rescue StandardError
129
+ Async.logger.error($!)
130
+ end
131
+
132
+ async def invoke(parent)
133
+ statistics = Statistics.new
134
+
135
+ @urls.each do |url|
136
+ endpoint = Async::HTTP::URLEndpoint.parse(url)
137
+
138
+ Async::HTTP::Client.open(endpoint, endpoint.protocol, connection_limit: 4) do |client|
139
+ fetch(statistics, client, endpoint.url).wait
140
+ end
141
+ end
142
+
143
+ statistics.print
144
+
145
+ return statistics
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'trenni/sanitize'
22
+
23
+ module Benchmark
24
+ module HTTP
25
+ class LinksFilter < Trenni::Sanitize::Filter
26
+ def initialize(*)
27
+ super
28
+
29
+ @base = nil
30
+ @links = []
31
+ end
32
+
33
+ attr :base
34
+ attr :links
35
+
36
+ def filter(node)
37
+ if node.name == 'base'
38
+ @base = node['href']
39
+ elsif node.name == 'a'
40
+ @links << node['href']
41
+ end
42
+
43
+ node.skip!(TAG)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -18,23 +18,38 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
+ require 'async/clock'
22
+
21
23
  module Benchmark
22
24
  module HTTP
23
- class Statistics
24
- def initialize(concurrency)
25
+ class Stopwatch
26
+ def initialize(concurrency = 0)
25
27
  @samples = []
26
- @duration = 0
28
+
29
+ @total_time = 0
30
+
31
+ # The number of currently executing measurements:
32
+ @count = 0
27
33
 
28
34
  @concurrency = concurrency
35
+ @start_time = nil
29
36
  end
30
37
 
38
+ # The individual samples' durations.
31
39
  attr :samples
32
- attr :duration
33
40
 
41
+ # The sequential time of all samples.
42
+ attr :total_time
43
+
44
+ # The maximum number of executing measurements at any one time.
34
45
  attr :concurrency
35
46
 
47
+ def duration
48
+ @samples.sum
49
+ end
50
+
36
51
  def sequential_duration
37
- @duration / @concurrency
52
+ duration / @concurrency
38
53
  end
39
54
 
40
55
  def count
@@ -42,11 +57,11 @@ module Benchmark
42
57
  end
43
58
 
44
59
  def per_second
45
- @samples.count.to_f / sequential_duration.to_f
60
+ @samples.count.to_f / total_time.to_f
46
61
  end
47
62
 
48
63
  def latency
49
- @duration.to_f / @samples.count.to_f
64
+ duration.to_f / count.to_f
50
65
  end
51
66
 
52
67
  def similar?(other, difference = 2.0)
@@ -61,13 +76,17 @@ module Benchmark
61
76
  end
62
77
  end
63
78
 
79
+ def valid?
80
+ @samples.count > 1
81
+ end
82
+
64
83
  # Computes Population Variance, σ^2.
65
84
  def variance
66
- return nil if @samples.count < 2
67
-
68
- average = self.average
69
-
70
- return @samples.map{|n| (n - average)**2}.sum / @samples.count
85
+ if valid?
86
+ average = self.average
87
+
88
+ return @samples.map{|n| (n - average)**2}.sum / @samples.count
89
+ end
71
90
  end
72
91
 
73
92
  # Population Standard Deviation, σ
@@ -83,16 +102,37 @@ module Benchmark
83
102
  end
84
103
  end
85
104
 
105
+ def add(duration, result = nil)
106
+ @samples << duration
107
+ end
108
+
86
109
  def measure
87
- start_time = Time.now
110
+ @count += 1
111
+
112
+ if @count > @concurrency
113
+ @concurrency = @count
114
+ end
115
+
116
+ start_time = Async::Clock.now
117
+
118
+ unless @start_time
119
+ @start_time = start_time
120
+ end
88
121
 
89
122
  result = yield
90
123
 
91
- duration = Time.now - start_time
92
- @samples << duration
93
- @duration += duration
124
+ end_time = Async::Clock.now
125
+
126
+ self.add(end_time - start_time, result)
94
127
 
95
128
  return result
129
+ ensure
130
+ @count -= 1
131
+
132
+ if @count == 0
133
+ @total_time += end_time - @start_time
134
+ @start_time = nil
135
+ end
96
136
  end
97
137
 
98
138
  def sample(confidence_factor, &block)
@@ -105,13 +145,46 @@ module Benchmark
105
145
  end
106
146
 
107
147
  def print(out = STDOUT)
108
- out.puts "#{@samples.count} samples. #{1.0 / self.average} per second. S/D: #{standard_deviation}."
148
+ if self.valid?
149
+ out.puts "#{@samples.count} samples. #{per_second} requests per second. S/D: #{Seconds[standard_deviation]}."
150
+ else
151
+ out.puts "Not enough samples."
152
+ end
109
153
  end
110
154
 
111
155
  private
112
156
 
113
157
  def confident?(factor)
114
- (@samples.count > @concurrency) && self.standard_error < (self.average * factor)
158
+ if @samples.count > @concurrency
159
+ return self.standard_error < (self.average * factor)
160
+ end
161
+
162
+ return false
163
+ end
164
+ end
165
+
166
+ class Statistics < Stopwatch
167
+ def initialize(*)
168
+ super
169
+
170
+ # The count of the status codes seen in the responses:
171
+ @responses = Hash.new{|h,k| 0}
172
+ end
173
+
174
+ def add(duration, result)
175
+ super
176
+
177
+ @responses[result.status] += 1
178
+ end
179
+
180
+ def print(out = STDOUT)
181
+ if valid?
182
+ counts = @responses.sort.collect{|status, count| "#{count}x #{status}"}.join("; ")
183
+
184
+ out.puts "#{@samples.count} samples: #{counts}. #{per_second.round(2)} requests per second. S/D: #{Seconds[standard_deviation]}."
185
+ else
186
+ out.puts "Not enough samples."
187
+ end
115
188
  end
116
189
  end
117
190
  end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Benchmark
22
22
  module HTTP
23
- VERSION = "0.2.0"
23
+ VERSION = "0.3.0"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: benchmark-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-27 00:00:00.000000000 Z
11
+ date: 2018-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async-io
@@ -30,14 +30,42 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.9'
33
+ version: 0.27.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.9'
40
+ version: 0.27.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: async-await
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: trenni-sanitize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: samovar
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -113,6 +141,8 @@ files:
113
141
  - lib/benchmark/http.rb
114
142
  - lib/benchmark/http/command.rb
115
143
  - lib/benchmark/http/command/concurrency.rb
144
+ - lib/benchmark/http/command/spider.rb
145
+ - lib/benchmark/http/links_filter.rb
116
146
  - lib/benchmark/http/seconds.rb
117
147
  - lib/benchmark/http/statistics.rb
118
148
  - lib/benchmark/http/version.rb