rhoconnect 3.0.6 → 3.1.0.beta1
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.
- 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 ""
|