rhoconnect 3.0.6 → 3.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +38 -17
- data/Rakefile +0 -10
- data/bench/benchapp/Gemfile.lock +1 -0
- data/bench/distr_bench/distr_bench_main +94 -27
- data/bench/distr_bench/run_test_query_script.sh +22 -18
- data/bench/lib/bench/aws_utils.rb +326 -0
- data/bench/lib/bench/bench_result_processor.rb +268 -75
- data/bench/lib/bench/cli.rb +1 -0
- data/bench/lib/bench/distr_runner.rb +102 -0
- data/bench/lib/bench/utils.rb +127 -0
- data/bench/lib/bench.rb +16 -15
- data/bench/prepare_bench +3 -11
- data/bench/scripts/test_query_script.rb +6 -7
- data/bin/rhoconnect-benchmark +257 -5
- data/doc/benchmarks-running.txt +140 -0
- data/doc/client-java.txt +236 -0
- data/doc/client-objc.txt +41 -1
- data/doc/client.txt +12 -0
- data/doc/command-line.txt +12 -3
- data/doc/cud-conflicts.txt +68 -0
- data/doc/deploying.txt +1 -70
- data/doc/hosting-rhohub.txt +3 -0
- data/doc/install.txt +50 -13
- data/doc/java-plugin.txt +217 -177
- data/doc/net-plugin.txt +97 -64
- data/doc/plugin-intro.txt +4 -2
- data/doc/preparing-production.txt +63 -0
- data/doc/rhoconnect-redis-stack.txt +252 -0
- data/doc/source-adapters.txt +3 -1
- data/doc/tutorial.txt +111 -49
- data/examples/simple/dump.rdb +0 -0
- data/installer/unix-like/rho_connect_install_constants.rb +6 -5
- data/installer/unix-like/rho_connect_install_installers.rb +6 -2
- data/installer/utils/nix_install_test.rb +2 -0
- data/installer/utils/package_upload/auto-repo.rb +136 -0
- data/installer/utils/package_upload/repos.rake +6 -3
- data/installer/utils/package_upload/s3_upload.rb +11 -6
- data/installer/windows/rhosync.nsi +5 -5
- data/lib/rhoconnect/client_sync.rb +2 -2
- data/lib/rhoconnect/document.rb +12 -0
- data/lib/rhoconnect/jobs/source_job.rb +2 -2
- data/lib/rhoconnect/predefined_adapters/bench_adapter.rb +61 -0
- data/lib/rhoconnect/source.rb +5 -0
- data/lib/rhoconnect/source_adapter.rb +10 -1
- data/lib/rhoconnect/source_sync.rb +161 -88
- data/lib/rhoconnect/store.rb +48 -0
- data/lib/rhoconnect/test_methods.rb +6 -6
- data/lib/rhoconnect/version.rb +1 -1
- data/lib/rhoconnect.rb +25 -2
- data/spec/apps/rhotestapp/sources/sample_adapter.rb +29 -0
- data/spec/jobs/source_job_spec.rb +5 -5
- data/spec/source_adapter_spec.rb +10 -0
- data/spec/source_sync_spec.rb +114 -33
- data/spec/spec_helper.rb +21 -2
- data/spec/store_spec.rb +29 -0
- data/spec/support/shared_examples.rb +1 -1
- data/spec/test_methods_spec.rb +4 -4
- data/tasks/redis.rake +2 -2
- metadata +59 -59
- data/bench/benchapp/log/passenger.3000.log +0 -1
- data/bench/benchapp/log/passenger.9292.log +0 -59
- data/bench/benchapp/tmp/pids/passenger.3000.pid.lock +0 -0
- data/bench/benchapp/tmp/pids/passenger.9292.pid.lock +0 -0
- data/bench/lib/testdata/0-data.txt +0 -0
- data/bench/lib/testdata/1-data.txt +0 -0
- data/bench/lib/testdata/10-data.txt +0 -15
- data/bench/lib/testdata/2-data.txt +0 -3
- data/bench/lib/testdata/25-data.txt +0 -39
- data/bench/lib/testdata/250-data.txt +0 -353
- data/bench/lib/testdata/3-data.txt +0 -4
- data/bench/lib/testdata/50-data.txt +0 -70
- data/bench/lib/testdata/500-data.txt +0 -711
@@ -0,0 +1,102 @@
|
|
1
|
+
module Bench
|
2
|
+
class DistrRunner
|
3
|
+
|
4
|
+
attr_accessor :start_time, :end_time, :clients_group
|
5
|
+
attr_accessor :total_count, :times_count, :times_sum
|
6
|
+
|
7
|
+
def initialize(clientgroup)
|
8
|
+
@clients_group = clientgroup
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(server, sync_key, payload, concurrency, niterations, result_filename=nil)
|
12
|
+
# 1) Extract server name
|
13
|
+
server ||= 'default'
|
14
|
+
if server != 'default'
|
15
|
+
Bench.base_url = server
|
16
|
+
end
|
17
|
+
|
18
|
+
# 2) Simulate the payload
|
19
|
+
Bench.datasize = payload.to_i
|
20
|
+
expected_data = Bench.get_test_data(Bench.datasize)
|
21
|
+
Bench.concurrency = concurrency.to_i
|
22
|
+
Bench.iterations = niterations.to_i
|
23
|
+
|
24
|
+
# 3) extract result filename
|
25
|
+
Bench.result_filename = result_filename
|
26
|
+
|
27
|
+
# 4) Set up the server
|
28
|
+
begin
|
29
|
+
Bench.admin_login = 'rhoadmin'
|
30
|
+
Bench.admin_password = ''
|
31
|
+
Bench.get_test_server
|
32
|
+
Bench.reset_app
|
33
|
+
Bench.user_name = "benchuser"
|
34
|
+
Bench.password = "password"
|
35
|
+
Bench.set_server_state("test_db_storage:application:#{Bench.user_name}",expected_data)
|
36
|
+
Bench.reset_refresh_time('RhoInternalBenchmarkAdapter')
|
37
|
+
|
38
|
+
#6) set the sync key
|
39
|
+
@start_time = Time.now + 10.0
|
40
|
+
Bench.set_server_state(sync_key, @start_time.to_f.to_s)
|
41
|
+
puts "Sync Key #{sync_key} is set to #{@start_time} - waiting for clients now!!!"
|
42
|
+
|
43
|
+
#7) Start-up all clients
|
44
|
+
command="cd /opt/rhoconnect/bin; ruby run_client_benchmark #{server} #{sync_key} #{niterations} 1 #{Bench.datasize} 1>/dev/null"
|
45
|
+
ec2_clients = clients_group.client_instances[0,concurrency]
|
46
|
+
Bench::AWSUtils.run_stack_ssh_command(ec2_clients, command)
|
47
|
+
|
48
|
+
#8) Wait until the command is done and save all data to the disk
|
49
|
+
sleep(1)
|
50
|
+
@total_count = 0
|
51
|
+
@start_time = 0.0
|
52
|
+
@end_time = 0.0
|
53
|
+
@times_sum = 0.0
|
54
|
+
@times_count = 0
|
55
|
+
process_results
|
56
|
+
save_results
|
57
|
+
|
58
|
+
#9) Clean-up the db
|
59
|
+
Bench.reset_app
|
60
|
+
rescue Exception => e
|
61
|
+
puts "Distributed Bench Runner ERROR !!!"
|
62
|
+
puts e.message
|
63
|
+
puts e.backtrace.join("\n")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def process_results
|
68
|
+
finished_data = Bench.get_server_state("bench_statistics_data")
|
69
|
+
finished_data.each do |session,session_data|
|
70
|
+
puts "Client data for #{session} : startTime (#{session_data['start_time']}), endTime (#{session_data['end_time']})"
|
71
|
+
@total_count += session_data['count'].to_i
|
72
|
+
@start_time = session_data['start_time'].to_f unless @start_time > 0.0 and session_data['start_time'].to_f >= @start_time
|
73
|
+
@end_time = session_data['end_time'].to_f unless session_data['end_time'].to_f <= @end_time
|
74
|
+
if not session_data['times'].nil?
|
75
|
+
times_data = session_data['times'].split(',')
|
76
|
+
@times_count += times_data.size
|
77
|
+
times_data.each do |timevalue|
|
78
|
+
@times_sum += timevalue.to_f
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def average_time
|
85
|
+
@times_count > 0 ? @times_sum/@times_count : 0.0
|
86
|
+
end
|
87
|
+
|
88
|
+
def save_results
|
89
|
+
return if Bench.result_filename.nil?
|
90
|
+
|
91
|
+
res_hash = YAML.load_file(Bench.result_filename) if File.exist?(Bench.result_filename)
|
92
|
+
res_hash ||= {}
|
93
|
+
puts "Overall results are : startTime (#{@start_time.to_s}), endTime (#{@end_time.to_s}), count (#{@total_count.to_s}), payload (#{Bench.datasize}), concurrency (#{Bench.concurrency})"
|
94
|
+
res_hash[Bench.concurrency.to_s] = (@end_time > 0.0 and @start_time > 0.0) ? [@total_count/(@end_time - @start_time)] : [0.0]
|
95
|
+
res_hash[Bench.concurrency.to_s] << average_time
|
96
|
+
File.open(Bench.result_filename, 'w' ) do |file|
|
97
|
+
file.write res_hash.to_yaml unless res_hash.empty?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
data/bench/lib/bench/utils.rb
CHANGED
@@ -53,5 +53,132 @@ module Bench
|
|
53
53
|
0
|
54
54
|
end
|
55
55
|
end
|
56
|
+
|
57
|
+
def create_subdir(dir)
|
58
|
+
begin
|
59
|
+
if File.directory? dir
|
60
|
+
dir += '_' + Time.now.strftime("%Y_%m_%d_%H_%M_%S")
|
61
|
+
end
|
62
|
+
Dir.mkdir(dir)
|
63
|
+
dir
|
64
|
+
rescue
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def load_settings(file)
|
69
|
+
begin
|
70
|
+
return YAML.load_file(file)
|
71
|
+
rescue Exception => e
|
72
|
+
puts "Error opening settings file #{file}: #{e}."
|
73
|
+
puts e.backtrace.join("\n")
|
74
|
+
raise e
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def start_rhoconnect_app(options)
|
79
|
+
options[:app_started] = false
|
80
|
+
path = options[:start_server] || '.'
|
81
|
+
if not File.exists?(File.join(path,'settings','settings.yml'))
|
82
|
+
puts " Invalid Rhoconnect app path '#{path}' - no app files can be found there"
|
83
|
+
return false
|
84
|
+
end
|
85
|
+
settings = load_settings(File.join(path,'settings','settings.yml'))
|
86
|
+
app_url = settings[:production][:syncserver].gsub(/\/$/,'')
|
87
|
+
|
88
|
+
uri = URI.parse(app_url)
|
89
|
+
port = (uri.port and uri.port != 80) ? ":"+uri.port.to_s : ""
|
90
|
+
options[:server_url] = "#{uri.scheme}://#{uri.host}#{port}"
|
91
|
+
|
92
|
+
already_running = check_rc_service(options[:server_url])
|
93
|
+
if already_running
|
94
|
+
puts " Another Rhoconnect Application is already running at '#{options[:server_url]}'"
|
95
|
+
return false
|
96
|
+
end
|
97
|
+
|
98
|
+
# start the app now
|
99
|
+
puts "Starting up the Rhoconnect Application at #{options[:server_url]}"
|
100
|
+
current_dir = Dir.pwd
|
101
|
+
Dir.chdir(path)
|
102
|
+
exit_code = system("rake rhoconnect:startbg")
|
103
|
+
sleep 1
|
104
|
+
Dir.chdir(current_dir)
|
105
|
+
|
106
|
+
options[:app_started] = check_rc_service(options[:server_url])
|
107
|
+
end
|
108
|
+
|
109
|
+
def stop_rhoconnect_app(options)
|
110
|
+
return unless options[:app_started] == true
|
111
|
+
|
112
|
+
path = options[:start_server] || '.'
|
113
|
+
if not File.exists?(File.join(path,'settings','settings.yml'))
|
114
|
+
puts " Invalid Rhoconnect app path '#{path}' - no app files can be found there"
|
115
|
+
return
|
116
|
+
end
|
117
|
+
puts "Stopping the Rhoconnect Application at #{options[:server_url]}"
|
118
|
+
current_dir = Dir.pwd
|
119
|
+
Dir.chdir(path)
|
120
|
+
system("rake rhoconnect:stop")
|
121
|
+
sleep 1
|
122
|
+
Dir.chdir(current_dir)
|
123
|
+
end
|
124
|
+
|
125
|
+
# check_rc_service
|
126
|
+
# Makes an HTTP request to check that the rhoconnect app is up and running
|
127
|
+
def check_rc_service(server_name)
|
128
|
+
success = false
|
129
|
+
begin
|
130
|
+
request = Net::HTTP.get_response(URI.parse("#{server_name}/console"))
|
131
|
+
if request.code == '200'
|
132
|
+
success = true
|
133
|
+
end
|
134
|
+
rescue
|
135
|
+
end
|
136
|
+
success
|
137
|
+
end #check_rc_service
|
138
|
+
|
139
|
+
# prepare bench results
|
140
|
+
def prepare_bench_results_dirs(dir)
|
141
|
+
start_dir = Dir.pwd
|
142
|
+
Dir.chdir dir
|
143
|
+
|
144
|
+
# create result directory structure
|
145
|
+
['bench_results'].each do |dir|
|
146
|
+
next if dir.nil?
|
147
|
+
created_dir = Bench.create_subdir dir
|
148
|
+
Dir.chdir created_dir
|
149
|
+
end
|
150
|
+
result_dir = Dir.pwd
|
151
|
+
['raw_data'].each do |dir|
|
152
|
+
Bench.create_subdir dir
|
153
|
+
end
|
154
|
+
|
155
|
+
Dir.chdir start_dir
|
156
|
+
result_dir
|
157
|
+
end
|
158
|
+
|
159
|
+
def prepare_bench_results_meta(dir, title, x_keys)
|
160
|
+
title ||= "Results"
|
161
|
+
|
162
|
+
start_dir = Dir.pwd
|
163
|
+
Dir.chdir(dir)
|
164
|
+
|
165
|
+
# 3) create meta.yml file
|
166
|
+
meta_hash = {:x_keys => {}, :metrics => {}, :label => title}
|
167
|
+
counter = 0
|
168
|
+
x_keys = x_keys.sort_by(&Bench.sort_natural_order)
|
169
|
+
x_keys.each do |x_key|
|
170
|
+
meta_hash[:x_keys][x_key] = counter
|
171
|
+
counter += 1
|
172
|
+
end
|
173
|
+
|
174
|
+
meta_hash[:metrics] = {'Throughput' => 0, 'Av.Time' => 1}
|
175
|
+
|
176
|
+
File.open(File.join(dir,'raw_data','meta.yml'), 'w') do |file|
|
177
|
+
file.write meta_hash.to_yaml unless meta_hash.empty?
|
178
|
+
end
|
179
|
+
|
180
|
+
Dir.chdir start_dir
|
181
|
+
true
|
182
|
+
end
|
56
183
|
end
|
57
184
|
end
|
data/bench/lib/bench.rb
CHANGED
@@ -4,6 +4,7 @@ $:.unshift File.dirname(__FILE__)
|
|
4
4
|
require 'bench/timer'
|
5
5
|
require 'bench/logging'
|
6
6
|
require 'bench/utils'
|
7
|
+
require 'bench/bench_result_processor'
|
7
8
|
require 'bench/result'
|
8
9
|
require 'bench/session'
|
9
10
|
require 'bench/runner'
|
@@ -53,6 +54,14 @@ module Bench
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
57
|
+
def get_server_license_info
|
58
|
+
token = get_token
|
59
|
+
params = {:api_token => token}
|
60
|
+
@body = RestClient.post("#{@host}/api/admin/get_license_info",
|
61
|
+
params.to_json, :content_type => :json)
|
62
|
+
JSON.parse(@body.to_s)
|
63
|
+
end
|
64
|
+
|
56
65
|
def get_server_state(doc)
|
57
66
|
token = get_token
|
58
67
|
params = {:api_token => token, :doc => doc}
|
@@ -110,15 +119,18 @@ module Bench
|
|
110
119
|
def get_test_server(app_name = nil)
|
111
120
|
if @base_url.nil?
|
112
121
|
app_name = 'benchapp' unless app_name
|
113
|
-
load_settings(File.join(File.dirname(__FILE__),'..',app_name,'settings','settings.yml'))
|
114
|
-
@base_url =
|
122
|
+
settings = load_settings(File.join(File.dirname(__FILE__),'..',app_name,'settings','settings.yml'))
|
123
|
+
@base_url = settings[:development][:syncserver].gsub(/\/$/,'')
|
115
124
|
end
|
116
125
|
uri = URI.parse(@base_url)
|
117
|
-
port = (uri.port and uri.port != 80) ? ":"+uri.port.to_s : ""
|
126
|
+
port = (uri.port and uri.port != 80) ? ":"+uri.port.to_s : ""
|
127
|
+
if not uri.scheme
|
128
|
+
raise "URI '#{@base_url}' is invalid:\n\t- doesn't have the required scheme part (for example , http://)"
|
129
|
+
end
|
118
130
|
@host = "#{uri.scheme}://#{uri.host}#{port}"
|
119
131
|
puts "Test server is #{@host}..."
|
120
132
|
end
|
121
|
-
|
133
|
+
|
122
134
|
def test(&block)
|
123
135
|
Runner.new.test(@concurrency,@iterations,&block)
|
124
136
|
end
|
@@ -140,16 +152,5 @@ module Bench
|
|
140
152
|
end
|
141
153
|
archive
|
142
154
|
end
|
143
|
-
|
144
|
-
# TODO: Share this code with the framework Rho class
|
145
|
-
def load_settings(file)
|
146
|
-
begin
|
147
|
-
$settings = YAML.load_file(file)
|
148
|
-
rescue Exception => e
|
149
|
-
puts "Error opening settings file #{file}: #{e}."
|
150
|
-
puts e.backtrace.join("\n")
|
151
|
-
raise e
|
152
|
-
end
|
153
|
-
end
|
154
155
|
end
|
155
156
|
end
|
data/bench/prepare_bench
CHANGED
@@ -4,27 +4,19 @@ require 'rubygems'
|
|
4
4
|
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
|
5
5
|
require 'bench'
|
6
6
|
|
7
|
-
def create_subdir(dir)
|
8
|
-
begin
|
9
|
-
Dir.mkdir(dir)
|
10
|
-
rescue
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
7
|
# 1) Extract Bench title
|
15
8
|
title = ARGV[0]
|
16
9
|
|
17
|
-
|
18
10
|
# 2) create result directory structure
|
19
11
|
['bench_results', ARGV[1]].each do |dir|
|
20
12
|
next if dir.nil?
|
21
|
-
create_subdir dir
|
13
|
+
Bench.create_subdir dir
|
22
14
|
Dir.chdir dir
|
23
15
|
end
|
24
16
|
result_dir = Dir.pwd
|
25
17
|
|
26
|
-
['raw_data'
|
27
|
-
create_subdir dir
|
18
|
+
['raw_data'].each do |dir|
|
19
|
+
Bench.create_subdir dir
|
28
20
|
end
|
29
21
|
|
30
22
|
# 3) create meta.yml file
|
@@ -2,15 +2,14 @@ include BenchHelpers
|
|
2
2
|
bench_log "Runs simple login,clientcreate,clientregister,sync session and validates response"
|
3
3
|
|
4
4
|
Bench.config do |config|
|
5
|
-
config.concurrency ||=
|
5
|
+
config.concurrency ||= 1
|
6
6
|
config.iterations ||= 10
|
7
7
|
config.datasize ||= 100
|
8
8
|
config.main_marker = 'get-cud'
|
9
9
|
config.user_name = "benchuser"
|
10
10
|
config.password = "password"
|
11
11
|
config.get_test_server
|
12
|
-
@datasize = Bench.datasize
|
13
|
-
@expected = Bench.get_test_data(@datasize)
|
12
|
+
@datasize = Bench.datasize
|
14
13
|
@all_objects = "[{\"version\":3},{\"token\":\"%s\"},{\"count\":%i},{\"progress_count\":0},{\"total_count\":%i},{\"insert\":""}]"
|
15
14
|
@ack_token = "[{\"version\":3},{\"token\":\"\"},{\"count\":0},{\"progress_count\":%i},{\"total_count\":%i},{}]"
|
16
15
|
@api_token = Bench.get_token
|
@@ -19,8 +18,9 @@ Bench.config do |config|
|
|
19
18
|
# if this is not a distributed run - reset the app
|
20
19
|
if not Bench.sync_key
|
21
20
|
config.reset_app
|
21
|
+
@expected = Bench.get_test_data(@datasize)
|
22
22
|
config.set_server_state("test_db_storage:application:#{config.user_name}",@expected)
|
23
|
-
config.reset_refresh_time('
|
23
|
+
config.reset_refresh_time('RhoInternalBenchmarkAdapter')
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -34,7 +34,6 @@ Bench.synchronize do |config|
|
|
34
34
|
end
|
35
35
|
sleep(0.010)
|
36
36
|
end
|
37
|
-
puts " we have here #{cur_time}, #{sync_time}"
|
38
37
|
end
|
39
38
|
|
40
39
|
Bench.test do |config,session|
|
@@ -50,11 +49,11 @@ Bench.test do |config,session|
|
|
50
49
|
end
|
51
50
|
|
52
51
|
session.get "get-cud", "#{config.base_url}/query" do
|
53
|
-
{'source_name' => '
|
52
|
+
{'source_name' => 'RhoInternalBenchmarkAdapter', 'client_id' => session.client_id, 'p_size' => @datasize}
|
54
53
|
end
|
55
54
|
token = JSON.parse(session.last_result.body)[1]['token']
|
56
55
|
session.get "ack-cud", "#{config.base_url}/query" do
|
57
|
-
{ 'source_name' => '
|
56
|
+
{ 'source_name' => 'RhoInternalBenchmarkAdapter',
|
58
57
|
'client_id' => session.client_id,
|
59
58
|
'token' => token}
|
60
59
|
end
|
data/bin/rhoconnect-benchmark
CHANGED
@@ -4,10 +4,262 @@ require 'rubygems'
|
|
4
4
|
$:.unshift File.join(File.dirname(__FILE__),'..','bench','lib')
|
5
5
|
$:.unshift File.join(File.dirname(__FILE__),'..','bench')
|
6
6
|
require 'bench'
|
7
|
+
require 'optparse'
|
7
8
|
|
8
|
-
|
9
|
-
$ARGV.unshift 'rhoadmin'
|
10
|
-
$ARGV.unshift 'scripts/test_comm_script.rb'
|
11
|
-
$ARGV.unshift 'start'
|
9
|
+
ENV['RACK_ENV']='production'
|
12
10
|
|
13
|
-
|
11
|
+
RHOCONNECT_PATH = File.join(File.dirname(__FILE__),'..')
|
12
|
+
puts "Rhoconnect-Benchmark Script is started at #{Time.now.to_s}"
|
13
|
+
|
14
|
+
def parse_options
|
15
|
+
begin
|
16
|
+
options = {}
|
17
|
+
optparse = OptionParser.new do |opts|
|
18
|
+
# Set a banner, displayed at the top
|
19
|
+
# of the help screen.
|
20
|
+
opts.banner = "Usage: rhoconnect-benchmark [options]"
|
21
|
+
|
22
|
+
options[:server_url] = 'http://localhost:9292'
|
23
|
+
opts.on( '-u', '--url URL', 'Use URL as a server for benchmarking' ) do |url|
|
24
|
+
options[:server_url] = url
|
25
|
+
end
|
26
|
+
|
27
|
+
options[:start_server] = nil
|
28
|
+
opts.on( '-s', '--startserver [APP_PATH]', 'Starts Rhoconnect App Server on localhost and use it for benchmarking' ) do |path|
|
29
|
+
options[:start_server] = path || '.'
|
30
|
+
end
|
31
|
+
|
32
|
+
options[:num_clients] = 0
|
33
|
+
opts.on( '-C', '--nclients NUMBER', 'Number of concurrent clients to use' ) do |number|
|
34
|
+
options[:num_clients] = number
|
35
|
+
end
|
36
|
+
|
37
|
+
options[:num_iterations] = 10
|
38
|
+
opts.on( '-R', '--niterations NUMBER', 'Number of iterations to run benchmark test on each client (default - 10)' ) do |number|
|
39
|
+
options[:num_iterations] = number
|
40
|
+
end
|
41
|
+
|
42
|
+
options[:payload] = 100
|
43
|
+
opts.on( '-p', '--payload NUMBER', 'Simulate payload (number of records), default - 100 recs (~20K)' ) do |number|
|
44
|
+
options[:payload] = number
|
45
|
+
end
|
46
|
+
|
47
|
+
options[:max_payload] = 100
|
48
|
+
opts.on( '-x', '--mapayload NUMBER', 'Run the benchmarks test varying the payload from 1 to NUMBER' ) do |number|
|
49
|
+
options[:max_payload] = number
|
50
|
+
options[:payload] = number
|
51
|
+
end
|
52
|
+
|
53
|
+
options[:max_clients] = 1
|
54
|
+
opts.on( '-m', '--maxclientloops NUMBER', 'Run the benchmarks test varying the number of clients from 1 to NUMBER' ) do |number|
|
55
|
+
options[:max_clients] = number
|
56
|
+
options[:num_clients] = number
|
57
|
+
end
|
58
|
+
|
59
|
+
options[:max_payload] = 0
|
60
|
+
opts.on( '-x', '--mapayload NUMBER', 'Run the benchmarks test varying the payload from 1 to NUMBER' ) do |number|
|
61
|
+
options[:max_payload] = number
|
62
|
+
options[:payload] = number
|
63
|
+
end
|
64
|
+
|
65
|
+
options[:save_results] = nil
|
66
|
+
options[:title] = 'QUERY'
|
67
|
+
opts.on( '-S', '--save [PATH]', 'Save all benchmark results in to the file structure at PATH') do |path|
|
68
|
+
options[:save_results] = path || '.'
|
69
|
+
options[:title] ||= 'QUERY'
|
70
|
+
end
|
71
|
+
|
72
|
+
opts.on('-t', '--title TITLE', "Name this benchmark's test results with the title TITLE") do |title|
|
73
|
+
options[:title] = title
|
74
|
+
end
|
75
|
+
|
76
|
+
opts.on( '-A', '--advanced', 'This convinience option combines -m 10 and -x 500') do
|
77
|
+
options[:max_payload] = 500
|
78
|
+
options[:payload] = 500
|
79
|
+
options[:max_clients] = 10
|
80
|
+
options[:num_clients] = 10
|
81
|
+
options[:title] ||= "QUERY"
|
82
|
+
options[:save_results] = '.'
|
83
|
+
end
|
84
|
+
|
85
|
+
options[:distributed] = nil
|
86
|
+
opts.on('-D', '--distributed FNAME', 'Run benchmark test from distributed AWS Cloud Formation using FNAME for options') do |fname|
|
87
|
+
options[:max_payload] = 500
|
88
|
+
options[:payload] = 500
|
89
|
+
options[:max_clients] = 10
|
90
|
+
options[:num_clients] = 10
|
91
|
+
options[:title] ||= "QUERY"
|
92
|
+
options[:save_results] = '.'
|
93
|
+
options[:distributed] = fname
|
94
|
+
end
|
95
|
+
|
96
|
+
# This displays the help screen, all programs are
|
97
|
+
# assumed to have this option.
|
98
|
+
opts.on( '-h', '--help', 'Display rhoconnect-benchmark help information' ) do
|
99
|
+
puts opts
|
100
|
+
exit 0
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
optparse.parse!
|
105
|
+
rescue SystemExit => se
|
106
|
+
exit 0
|
107
|
+
rescue Exception => e
|
108
|
+
puts " Error while parsing the command line options: #{e.message}"
|
109
|
+
puts ""
|
110
|
+
puts optparse.help
|
111
|
+
puts ""
|
112
|
+
raise ""
|
113
|
+
end
|
114
|
+
|
115
|
+
options
|
116
|
+
end
|
117
|
+
|
118
|
+
begin
|
119
|
+
options = parse_options
|
120
|
+
# 1) start up the application - if required
|
121
|
+
# NOTE: server URL will be updated
|
122
|
+
# from the app's settings
|
123
|
+
if options[:start_server] != nil
|
124
|
+
if not Bench.start_rhoconnect_app(options)
|
125
|
+
puts " Cannot start rhoconnect application at path '#{options[:start_server]}'"
|
126
|
+
puts " Exiting..."
|
127
|
+
exit 10
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# 2) Now, parse the server's options
|
132
|
+
Bench.base_url = "#{options[:server_url]}/api/application"
|
133
|
+
Bench.get_test_server
|
134
|
+
Bench.admin_login = 'rhoadmin'
|
135
|
+
Bench.admin_password = ''
|
136
|
+
#
|
137
|
+
if not Bench.check_rc_service(Bench.host)
|
138
|
+
puts ""
|
139
|
+
puts " In order to run benchmark tests - you need to have the Rhoconnect application"
|
140
|
+
puts " up and running on #{options[:server_url]}"
|
141
|
+
puts ""
|
142
|
+
exit 10
|
143
|
+
end
|
144
|
+
|
145
|
+
# get license info from the server
|
146
|
+
rc_license_info = Bench.get_server_license_info
|
147
|
+
|
148
|
+
if options[:num_clients] == 0
|
149
|
+
n_clients = rc_license_info['seats'].to_i / options[:num_iterations]
|
150
|
+
if n_clients > 20
|
151
|
+
n_clients = 20
|
152
|
+
end
|
153
|
+
options[:num_clients] = n_clients
|
154
|
+
end
|
155
|
+
# calculate appropriate numbers for concurrency
|
156
|
+
total_num_clients = options[:num_iterations].to_i*options[:num_clients].to_i
|
157
|
+
if total_num_clients > rc_license_info['seats']
|
158
|
+
puts ""
|
159
|
+
puts " In order to run benchmark tests with #{options[:num_clients]} concurrent clients"
|
160
|
+
puts " for #{options[:num_iterations]} iterations you need to have a license with at least #{total_num_clients} seats."
|
161
|
+
puts " Your application have only #{rc_license_info['seats']} seats available."
|
162
|
+
puts " Adjust the number of concurrent clients or number of iterations to fit within the available license."
|
163
|
+
puts ""
|
164
|
+
exit 10
|
165
|
+
end
|
166
|
+
|
167
|
+
# run test in a loop from 1 to max_clients concurrency
|
168
|
+
concurrency_array = []
|
169
|
+
if options[:max_clients].to_i > 1
|
170
|
+
concurrency_array << 1
|
171
|
+
num_loops = 5
|
172
|
+
loop_step = (options[:max_clients].to_f - 1.to_f)/(num_loops - 1)
|
173
|
+
for i in 1..num_loops-2
|
174
|
+
concurrency_array << (1 + i*loop_step + 0.5).to_i
|
175
|
+
end
|
176
|
+
end
|
177
|
+
concurrency_array << options[:num_clients].to_i
|
178
|
+
concurrency_array.uniq!
|
179
|
+
|
180
|
+
# run test in a loop from 1 to max_payload records
|
181
|
+
payload_array = []
|
182
|
+
if options[:max_payload].to_i > 1
|
183
|
+
payload_array << 1
|
184
|
+
num_loops = 10
|
185
|
+
loop_step = (options[:max_payload].to_f - 1.to_f)/(num_loops - 1)
|
186
|
+
for i in 1..num_loops-2
|
187
|
+
payload_array << (1 + i*loop_step + 0.5).to_i
|
188
|
+
end
|
189
|
+
end
|
190
|
+
payload_array << options[:payload].to_i
|
191
|
+
payload_array.uniq!
|
192
|
+
|
193
|
+
# load distributed options and create the AWS Cloud Formation Stack
|
194
|
+
if options[:distributed] != nil
|
195
|
+
puts ""
|
196
|
+
puts " Creating Distributed Clients Benchmark"
|
197
|
+
puts ""
|
198
|
+
require 'bench/aws_utils'
|
199
|
+
require 'bench/distr_runner'
|
200
|
+
Bench::AWSUtils.init_connection(options[:distributed])
|
201
|
+
options[:clients_group] = nil
|
202
|
+
options[:clients_group] = Bench::AWSUtils.create_cf_stack
|
203
|
+
exit 10 unless options[:clients_group]
|
204
|
+
options[:distr_runner] = Bench::DistrRunner.new options[:clients_group]
|
205
|
+
end
|
206
|
+
|
207
|
+
# load the save results options
|
208
|
+
result_dir = nil
|
209
|
+
if options[:save_results]
|
210
|
+
result_dir = Bench.prepare_bench_results_dirs(options[:save_results])
|
211
|
+
x_keys = concurrency_array.collect {|t| t.to_s }
|
212
|
+
Bench.prepare_bench_results_meta(result_dir, options[:title], x_keys)
|
213
|
+
end
|
214
|
+
|
215
|
+
concurrency_array.each do |concurrency|
|
216
|
+
payload_array.each do |payload|
|
217
|
+
# initialize default parameters
|
218
|
+
bench_args = []
|
219
|
+
# Thor's task
|
220
|
+
bench_args[0] = 'start'
|
221
|
+
# script
|
222
|
+
bench_args[1] = 'scripts/test_query_script.rb'
|
223
|
+
# admin
|
224
|
+
bench_args[2] = 'rhoadmin'
|
225
|
+
# admin's password
|
226
|
+
bench_args[3] = ''
|
227
|
+
# server's URL
|
228
|
+
bench_args[4] = Bench.base_url
|
229
|
+
# result fname
|
230
|
+
result_fname = nil
|
231
|
+
result_fname = File.join(result_dir,'raw_data',"bench_result.#{payload}") if result_dir
|
232
|
+
bench_args[5] = result_fname
|
233
|
+
# concurrency
|
234
|
+
bench_args[6] = concurrency
|
235
|
+
# number of iterations
|
236
|
+
bench_args[7] = options[:num_iterations]
|
237
|
+
# datasize
|
238
|
+
bench_args[8] = payload
|
239
|
+
|
240
|
+
# now execute Bench
|
241
|
+
if(options[:distributed])
|
242
|
+
sync_key = "#{options[:title]}_#{payload}"
|
243
|
+
options[:distr_runner].run(Bench.base_url, sync_key, payload, concurrency, options[:num_iterations], result_fname)
|
244
|
+
else
|
245
|
+
Bench::Cli.start bench_args
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# once finished - post-process results
|
251
|
+
Bench::PostProcessing.execute result_dir
|
252
|
+
rescue Exception => e
|
253
|
+
puts e.message
|
254
|
+
ensure
|
255
|
+
if options and options[:app_started] == true
|
256
|
+
Bench.stop_rhoconnect_app(options)
|
257
|
+
end
|
258
|
+
|
259
|
+
if options and options[:clients_group]
|
260
|
+
Bench::AWSUtils.delete_cf_stack(options[:clients_group].stack_name)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
puts "Rhoconnect-Benchmark Script is finished at #{Time.now.to_s}"
|
265
|
+
puts ""
|