drnbench 1.0.1 → 1.0.2

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: 029ac85e0d002dfaf7636ea8031f29fd811deb42
4
- data.tar.gz: dfa72f28ebe5c95ad0dfa38f3bedd124fcf4c108
3
+ metadata.gz: bc7f61f1275e4e48a15492d197552728429a7272
4
+ data.tar.gz: fa6bd343d6a874c165dd95ae77bdc1ca7df730b1
5
5
  SHA512:
6
- metadata.gz: 0c2b179e22d3acb8d4e2c3592789bb5017da991eb17e053431ce5e4a12fd7cca4f7fe4a5ac8a77a5bd5bfbaabd1752147cb8edbf0ee8a34195ae6f49c729c318
7
- data.tar.gz: 97008b59cc5eb84afc94fce74f62fd89ae9e31b6bbfa1afe463c6404f062304dd8f6339c3271d9722f673491e6206b8428b60e54c3bd0dc05271300ad93d59da
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
- * Report throughput more correctly.
6
- * Report percentages of returned HTTP statuses correctly.
7
- * Report max elapsed time correctly.
8
- * Add ability to report slow requests.
9
- * Accept pattern group specific parameters.
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
 
@@ -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
- @result << {
46
- :request => request,
47
- :status => response.code,
48
- :elapsed_time => Time.now - start_time,
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
- "#{result[:elapsed_time]} sec: " +
86
- "#{request["method"]} http://#{request["host"]}:#{request["port"]}#{request["path"]}"
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
@@ -14,5 +14,5 @@
14
14
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
15
 
16
16
  module Drnbench
17
- VERSION = "1.0.1"
17
+ VERSION = "1.0.2"
18
18
  end
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.1
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-29 00:00:00.000000000 Z
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