drnbench 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/drnbench-extract-searchterms +56 -0
- data/bin/drnbench-generate-select-patterns +112 -0
- data/bin/drnbench-publish-subscribe +2 -0
- data/bin/drnbench-request-response +10 -0
- data/doc/text/news.md +16 -5
- data/lib/drnbench/client/http.rb +41 -6
- data/lib/drnbench/request-response/configuration.rb +4 -2
- data/lib/drnbench/request-response/gradual-runner.rb +6 -0
- data/lib/drnbench/request-response/result.rb +18 -2
- data/lib/drnbench/request-response/runner.rb +1 -0
- data/lib/drnbench/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc7f61f1275e4e48a15492d197552728429a7272
|
4
|
+
data.tar.gz: fa6bd343d6a874c165dd95ae77bdc1ca7df730b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 226d64e8c67139749313e265c3c6be5ac369b2c03f38dfc269dc2f9a105d682aad9830639e86ebef914306027fbf9ae64001773d4058983a14a307a101b352be
|
7
|
+
data.tar.gz: a97fea6987677e63f4f6511148cec0c30b98646042d5603c9dc61c10cf81325c117cea3ac5f82b794916ef69a6cc7309276fc90657cc7ce60f5b09d71f8b88ae
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require "drnbench"
|
19
|
+
require "ostruct"
|
20
|
+
require "optparse"
|
21
|
+
require "json"
|
22
|
+
|
23
|
+
options = OpenStruct.new
|
24
|
+
options.column_index = 0
|
25
|
+
|
26
|
+
option_parser = OptionParser.new do |parser|
|
27
|
+
parser.version = Drnbench::VERSION
|
28
|
+
|
29
|
+
parser.on("--column-index=INDEX", Integer,
|
30
|
+
"Index number of the column to be extracted.",
|
31
|
+
"(#{options.output_column_index})") do |index|
|
32
|
+
options.column_index = index
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
groonga_select_result_files = option_parser.parse!(ARGV)
|
37
|
+
|
38
|
+
def output_column_value(select_result, column_index)
|
39
|
+
select_result = JSON.parse(select_result)
|
40
|
+
body = select_result[1]
|
41
|
+
search_result = body.first
|
42
|
+
records = search_result[2..-1]
|
43
|
+
records.each do |record|
|
44
|
+
puts record[column_index]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
if groonga_select_result_files.empty?
|
49
|
+
output_column_value($stdin.read, options.column_index)
|
50
|
+
else
|
51
|
+
groonga_select_result_files.each do |select_result_file|
|
52
|
+
File.open(select_result_file) do |input|
|
53
|
+
output_column_value(input.read, options.column_index)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (C) 2014 Droonga Project
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require "drnbench"
|
19
|
+
require "ostruct"
|
20
|
+
require "optparse"
|
21
|
+
require "json"
|
22
|
+
|
23
|
+
options = {
|
24
|
+
:base_params => "limit=10&offset=0",
|
25
|
+
:hosts => [],
|
26
|
+
}
|
27
|
+
|
28
|
+
option_parser = OptionParser.new do |parser|
|
29
|
+
parser.version = Drnbench::VERSION
|
30
|
+
|
31
|
+
parser.on("--base-params=PARAMS",
|
32
|
+
"Base parameters for each select request",
|
33
|
+
"(#{options[:base_params]})") do |params|
|
34
|
+
options[:base_params] = params
|
35
|
+
end
|
36
|
+
|
37
|
+
parser.on("--hosts=NAME1,NAME2,...", Array,
|
38
|
+
"Target hosts to be requested parallely") do |hosts|
|
39
|
+
options[:hosts] = hosts
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
searchterms_files = option_parser.parse!(ARGV)
|
44
|
+
|
45
|
+
def sanitize_for_param(value)
|
46
|
+
value.to_s
|
47
|
+
.gsub(/[:;]/, " ")
|
48
|
+
.strip
|
49
|
+
.gsub(/ +/, "%20")
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate_patterns(params)
|
53
|
+
host = params[:host]
|
54
|
+
frequency = params[:frequency] || 1.0
|
55
|
+
searchterms = params[:searchterms] || []
|
56
|
+
base_params = params[:base_params] || ""
|
57
|
+
|
58
|
+
request_patterns = searchterms.collect do |searchterm|
|
59
|
+
query_params = "query=#{sanitize_for_param(searchterm)}"
|
60
|
+
unless base_params.empty?
|
61
|
+
query_params = "#{base_params}&#{query_params}"
|
62
|
+
end
|
63
|
+
{
|
64
|
+
"path" => "/d/select?#{query_params}",
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
pattern = {
|
69
|
+
"frequency" => frequency,
|
70
|
+
"method" => "get",
|
71
|
+
"patterns" => request_patterns,
|
72
|
+
}
|
73
|
+
|
74
|
+
if host
|
75
|
+
pattern["host"] = host
|
76
|
+
{ "with-query-#{host}" => pattern }
|
77
|
+
else
|
78
|
+
{ "with-query" => pattern }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def output_patterns(params)
|
83
|
+
patterns = {}
|
84
|
+
|
85
|
+
hosts = params[:hosts] || []
|
86
|
+
if hosts.empty?
|
87
|
+
patterns.merge!(generate_patterns(params))
|
88
|
+
else
|
89
|
+
hosts.each do |host|
|
90
|
+
host_params = params.merge(:host => host,
|
91
|
+
:frequency => 1.0 / hosts.size)
|
92
|
+
host_patterns = generate_patterns(host_params)
|
93
|
+
patterns.merge!(host_patterns)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
puts JSON.pretty_generate(patterns)
|
98
|
+
end
|
99
|
+
|
100
|
+
if searchterms_files.empty?
|
101
|
+
searchterms = $stdin.read.split(/\r?\n/)
|
102
|
+
output_patterns(options.merge(:searchterms => searchterms))
|
103
|
+
else
|
104
|
+
searchterms_files.each do |searchterms_file|
|
105
|
+
File.open(searchterms_file) do |input|
|
106
|
+
searchterms = input.read.split(/\r?\n/)
|
107
|
+
output_patterns(options.merge(:searchterms => searchterms))
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
@@ -22,6 +22,8 @@ require "shellwords"
|
|
22
22
|
|
23
23
|
config = Drnbench::PublishSubscribe::Configuration.new
|
24
24
|
option_parser = OptionParser.new do |parser|
|
25
|
+
parser.version = Drnbench::VERSION
|
26
|
+
|
25
27
|
parser.on("--start-n-subscribers=N", Integer,
|
26
28
|
"initial number of subscribers") do |n_subscribers|
|
27
29
|
config.start_n_subscribers = n_subscribers
|
@@ -21,6 +21,8 @@ require "optparse"
|
|
21
21
|
|
22
22
|
config = Drnbench::RequestResponse::Configuration.new
|
23
23
|
option_parser = OptionParser.new do |parser|
|
24
|
+
parser.version = Drnbench::VERSION
|
25
|
+
|
24
26
|
parser.on("--duration=SECONDS", Float,
|
25
27
|
"duration of the benmark") do |duration|
|
26
28
|
config.duration = duration
|
@@ -29,6 +31,10 @@ option_parser = OptionParser.new do |parser|
|
|
29
31
|
"wait for each request") do |wait|
|
30
32
|
config.wait = wait
|
31
33
|
end
|
34
|
+
parser.on("--interval=SECONDS", Float,
|
35
|
+
"interval for each gradual case") do |interval|
|
36
|
+
config.interval = interval
|
37
|
+
end
|
32
38
|
parser.on("--start-n-clients=N", Integer,
|
33
39
|
"initial number of clients (optional)") do |n_clients|
|
34
40
|
config.start_n_clients = n_clients
|
@@ -74,6 +80,10 @@ option_parser = OptionParser.new do |parser|
|
|
74
80
|
"default HTTP method (optional)") do |method|
|
75
81
|
config.default_method = method
|
76
82
|
end
|
83
|
+
parser.on("--default-timeout=SECONDS", Float,
|
84
|
+
"default timeout (optional)") do |timeout|
|
85
|
+
config.default_timeout = timeout
|
86
|
+
end
|
77
87
|
|
78
88
|
parser.on("--output-path=PATH",
|
79
89
|
"path to output statistics as a CSV file (optional)") do |path|
|
data/doc/text/news.md
CHANGED
@@ -1,12 +1,23 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 1.0.2: 2014-07-30
|
4
|
+
|
5
|
+
* 'drnbench-request-response'
|
6
|
+
* Report aborted requests as slow requests.
|
7
|
+
* Report response status and index for slow requests.
|
8
|
+
* Add ability to specify default timeout via the `--default-timeout` option.
|
9
|
+
* Add ability to specify interval between each benchamrk via the `--interval` option.
|
10
|
+
* New utility command `drnbench-extract-searchterms` to extract values of a specific column from a result of Groonga's select command.
|
11
|
+
* New utility command `drnbench-generate-select-patterns` to generate patterns file for benchmark of Groonga's select command via HTTP.
|
12
|
+
|
3
13
|
## 1.0.1: 2014-07-29
|
4
14
|
|
5
|
-
*
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
15
|
+
* `drnbench-request-response`
|
16
|
+
* Report throughput more correctly.
|
17
|
+
* Report percentages of returned HTTP statuses correctly.
|
18
|
+
* Report max elapsed time correctly.
|
19
|
+
* Add ability to report slow requests via the `--n-slow-requests` option.
|
20
|
+
* Accept pattern group specific parameters.
|
10
21
|
|
11
22
|
## 1.0.0: 2014-01-29
|
12
23
|
|
data/lib/drnbench/client/http.rb
CHANGED
@@ -23,10 +23,15 @@ module Drnbench
|
|
23
23
|
|
24
24
|
SUPPORTED_HTTP_METHODS = ["GET", "POST"]
|
25
25
|
|
26
|
+
@@count = 0
|
27
|
+
|
26
28
|
def initialize(params, config)
|
27
29
|
@requests = params[:requests]
|
28
30
|
@result = params[:result]
|
29
31
|
@config = config
|
32
|
+
@count = 0
|
33
|
+
@id = @@count
|
34
|
+
@@count += 1
|
30
35
|
end
|
31
36
|
|
32
37
|
def run
|
@@ -37,16 +42,34 @@ module Drnbench
|
|
37
42
|
|
38
43
|
client = Droonga::Client.new(:protocol => :http,
|
39
44
|
:host => request["host"],
|
40
|
-
:port => request["port"]
|
45
|
+
:port => request["port"],
|
46
|
+
:timeout => request["timeout"])
|
41
47
|
request["headers"] ||= {}
|
42
48
|
request["headers"]["user-agent"] = "Ruby/#{RUBY_VERSION} Droonga::Benchmark::Runner::HttpClient"
|
43
49
|
start_time = Time.now
|
50
|
+
@last_request = request
|
51
|
+
@last_start_time = start_time
|
52
|
+
begin
|
44
53
|
response = client.request(request)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
54
|
+
@result << {
|
55
|
+
:request => request,
|
56
|
+
:status => response.code,
|
57
|
+
:elapsed_time => Time.now - start_time,
|
58
|
+
:client => @id,
|
59
|
+
:index => @count,
|
60
|
+
}
|
61
|
+
rescue Timeout::Error
|
62
|
+
@result << {
|
63
|
+
:request => request,
|
64
|
+
:status => "0",
|
65
|
+
:elapsed_time => Time.now - start_time,
|
66
|
+
:client => @id,
|
67
|
+
:index => @count,
|
68
|
+
}
|
69
|
+
end
|
70
|
+
@last_request = nil
|
71
|
+
@last_start_time = nil
|
72
|
+
@count += 1
|
50
73
|
sleep @config.wait
|
51
74
|
end
|
52
75
|
end
|
@@ -55,6 +78,17 @@ module Drnbench
|
|
55
78
|
|
56
79
|
def stop
|
57
80
|
@thread.exit
|
81
|
+
|
82
|
+
if @last_request
|
83
|
+
@result << {
|
84
|
+
:request => @last_request,
|
85
|
+
:status => "0",
|
86
|
+
:elapsed_time => Time.now - @last_start_time,
|
87
|
+
:client => @id,
|
88
|
+
:index => @count,
|
89
|
+
:last => true,
|
90
|
+
}
|
91
|
+
end
|
58
92
|
end
|
59
93
|
|
60
94
|
private
|
@@ -67,6 +101,7 @@ module Drnbench
|
|
67
101
|
unless SUPPORTED_HTTP_METHODS.include?(request["method"])
|
68
102
|
request["method"] = "GET"
|
69
103
|
end
|
104
|
+
request["timeout"] ||= @config.default_timeout
|
70
105
|
request
|
71
106
|
end
|
72
107
|
end
|
@@ -18,10 +18,10 @@ require "json"
|
|
18
18
|
module Drnbench
|
19
19
|
module RequestResponse
|
20
20
|
class Configuration
|
21
|
-
attr_accessor :duration, :wait, :request_patterns_file
|
21
|
+
attr_accessor :duration, :wait, :interval, :request_patterns_file
|
22
22
|
attr_accessor :start_n_clients, :end_n_clients, :step, :n_requests, :n_slow_requests
|
23
23
|
attr_accessor :mode
|
24
|
-
attr_accessor :default_host, :default_port, :default_path, :default_method
|
24
|
+
attr_accessor :default_host, :default_port, :default_path, :default_method, :default_timeout
|
25
25
|
attr_accessor :report_progressively, :output_path
|
26
26
|
|
27
27
|
MIN_DURATION = 1
|
@@ -29,6 +29,7 @@ module Drnbench
|
|
29
29
|
|
30
30
|
def initialize
|
31
31
|
@wait = 1
|
32
|
+
@interval = 5
|
32
33
|
@start_n_clients = 1
|
33
34
|
@end_n_clients = 1
|
34
35
|
@step = 1
|
@@ -40,6 +41,7 @@ module Drnbench
|
|
40
41
|
@default_port = 80
|
41
42
|
@default_path = "/"
|
42
43
|
@default_method = "GET"
|
44
|
+
@default_timeout = 5.0
|
43
45
|
|
44
46
|
@report_progressively = true
|
45
47
|
@output_path = "/tmp/drnbench-result.csv"
|
@@ -34,6 +34,8 @@ module Drnbench
|
|
34
34
|
def run_benchmarks
|
35
35
|
@result = Result.new
|
36
36
|
@config.start_n_clients.step(@config.end_n_clients, @config.step) do |n_clients|
|
37
|
+
sleep @config.interval unless @result.empty?
|
38
|
+
|
37
39
|
benchmark = Runner.new(n_clients, @config)
|
38
40
|
if @config.report_progressively
|
39
41
|
puts "Running benchmark with #{n_clients} clients..."
|
@@ -57,6 +59,10 @@ module Drnbench
|
|
57
59
|
@results[result.n_clients] = result
|
58
60
|
end
|
59
61
|
|
62
|
+
def empty?
|
63
|
+
@results.empty?
|
64
|
+
end
|
65
|
+
|
60
66
|
def statuses
|
61
67
|
@statuses ||= prepare_statuses
|
62
68
|
end
|
@@ -55,6 +55,10 @@ module Drnbench
|
|
55
55
|
@total_elapsed_time += result[:elapsed_time]
|
56
56
|
end
|
57
57
|
|
58
|
+
def empty?
|
59
|
+
@results.empty?
|
60
|
+
end
|
61
|
+
|
58
62
|
def total_n_requests
|
59
63
|
@total_n_requests ||= @results.size
|
60
64
|
end
|
@@ -82,8 +86,19 @@ module Drnbench
|
|
82
86
|
def top_slow_requests
|
83
87
|
slow_requests[0..@n_slow_requests-1].collect do |result|
|
84
88
|
request = result[:request]
|
85
|
-
|
86
|
-
|
89
|
+
status = result[:status].to_i
|
90
|
+
if status.zero?
|
91
|
+
status = "#{status}(aborted)"
|
92
|
+
end
|
93
|
+
index = result[:index]
|
94
|
+
index = "#{index}(last)" if result[:last]
|
95
|
+
[
|
96
|
+
"#{result[:elapsed_time]} sec:",
|
97
|
+
request["method"],
|
98
|
+
status,
|
99
|
+
"<#{result[:client]}>#{index}",
|
100
|
+
"http://#{request["host"]}:#{request["port"]}#{request["path"]}",
|
101
|
+
].join(" ")
|
87
102
|
end
|
88
103
|
end
|
89
104
|
|
@@ -105,6 +120,7 @@ module Drnbench
|
|
105
120
|
" max: #{max_elapsed_time} sec\n" +
|
106
121
|
" average: #{average_elapsed_time} sec\n" +
|
107
122
|
"Top #{@n_slow_requests} slow requests:\n" +
|
123
|
+
" [time: method status <client>index url]\n" +
|
108
124
|
top_slow_requests.collect do |request|
|
109
125
|
" #{request}"
|
110
126
|
end.join("\n")
|
@@ -113,6 +113,7 @@ module Drnbench
|
|
113
113
|
pattern["host"] ||= request_pattern["host"]
|
114
114
|
pattern["port"] ||= request_pattern["port"]
|
115
115
|
pattern["method"] ||= request_pattern["method"]
|
116
|
+
pattern["timeout"] ||= request_pattern["timeout"]
|
116
117
|
@requests << pattern
|
117
118
|
end
|
118
119
|
end
|
data/lib/drnbench/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: drnbench
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YUKI Hiroshi
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-07-
|
12
|
+
date: 2014-07-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
@@ -114,6 +114,8 @@ email:
|
|
114
114
|
- yuki@clear-code.com
|
115
115
|
- kou@clear-code.com
|
116
116
|
executables:
|
117
|
+
- drnbench-extract-searchterms
|
118
|
+
- drnbench-generate-select-patterns
|
117
119
|
- drnbench-request-response
|
118
120
|
- drnbench-publish-subscribe
|
119
121
|
extensions: []
|
@@ -142,6 +144,8 @@ files:
|
|
142
144
|
- lib/drnbench/server/engine.rb
|
143
145
|
- lib/drnbench/server/configuration.rb
|
144
146
|
- lib/drnbench.rb
|
147
|
+
- bin/drnbench-extract-searchterms
|
148
|
+
- bin/drnbench-generate-select-patterns
|
145
149
|
- bin/drnbench-request-response
|
146
150
|
- bin/drnbench-publish-subscribe
|
147
151
|
homepage: https://github.com/groonga/grntest
|