Description:
load test reads site_url from command line
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r315:faf1f66729ca - - 5 files changed: 28 inserted, 182 deleted

@@ -1,7 +1,7
1 1 How to call
2 2 ===========
3 3
4 4 Load test for front page:
5 5
6 - ruby runner.rb common_visitors.rb FirstPageViewer 10 -t 10
6 + ruby runner.rb common_visitors.rb FirstPageViewer 20 -t 10 --site_url=http://localhost/cafe
7 7
@@ -1,7 +1,8
1 - visitor "FirstPageViewer" do
2 - stores_cookies
1 + if !defined? VISITOR_OPTION_LIST
2 + VISITOR_OPTION_LIST = {}
3 + end
3 4
4 - site_url "http://localhost:3000"
5 -
5 + visitor "FirstPageViewer", VISITOR_OPTION_LIST do
6 + stores_cookies
6 7 get "/"
7 8 end
@@ -37,121 +37,131
37 37 if !FileTest.exists? TEMP_DIR
38 38 Dir.mkdir TEMP_DIR
39 39 end
40 40 end
41 41
42 42 def runner(visitor_lists, load_time=60, options={})
43 43 visitors = []
44 44 vcount = 0
45 45
46 46 visitor_lists.each do |cname, num|
47 47 begin
48 48 c = Kernel.const_get(cname)
49 49
50 50 num.times do
51 51 visitors[vcount] = c.new(vcount+1, TEMP_DIR)
52 52 visitors[vcount].talkative = true
53 53 vcount += 1
54 54 end
55 55 rescue NameError
56 56 puts "Can't find class #{cname}"
57 57 show_usage
58 58 exit(0)
59 59 end
60 60 end
61 61
62 62 puts "Having #{vcount} visitors"
63 63
64 64 vthread = []
65 65
66 66 all_start_time = Time.new
67 67
68 68 # start all visitors
69 69 vcount.times do |i|
70 70 vthread[i] = Thread.new do
71 71 visitors[i].run(:forever,options)
72 72 end
73 73 end
74 74
75 75 # wait for load_time seconds
76 76 sleep load_time
77 77
78 78 visitors.each do |visitor| visitor.stop! end
79 79
80 80 all_finish_time = Time.new
81 81
82 82 begin
83 83 # wait for all threads to stop
84 84 vcount.times do |i|
85 85 #puts "Waiting for thread #{i}, #{vthread[i].alive?}"
86 86 vthread[i].join
87 87 end
88 88
89 89 rescue Interrupt
90 90 # kill all remaining threads
91 91 vcount.times do |i|
92 92 vthread[i].kill if vthread[i].alive?
93 93 end
94 94 end
95 95
96 96 # clean up
97 97 visitors.each do |visitor|
98 98 #puts "Clean up: #{visitor.id}"
99 99 visitor.cleanup
100 100 end
101 101
102 102 #all_finish_time = Time.new
103 103
104 104 total_req = 0
105 105
106 106 vcount.times do |i|
107 107 stat = visitors[i].statistics
108 108 # puts "TYPE: #{visitors[i].class}"
109 109 # puts "Total requested = #{stat[:num_requested]}"
110 110 # puts "Average = #{stat[:avg_request_time]}"
111 111 # puts "S.D. = #{stat[:std_dev]}"
112 112 total_req += stat[:num_requested]
113 113 end
114 114
115 115 elapsed_time = all_finish_time - all_start_time
116 116
117 117 puts
118 118 puts "Total time = #{elapsed_time} sec."
119 119 puts "Total requests = #{total_req}"
120 120 puts "Trans. per sec = #{total_req/elapsed_time}"
121 121 end
122 122
123 123 ###########################
124 124 # MAIN
125 125 ###########################
126 126
127 127 if ARGV.length==0
128 128 show_usage
129 129 exit(0)
130 130 end
131 131
132 132 visitor_file = ARGV.shift
133 - require visitor_file
134 133
135 134 load_time = 60
136 135 dry_run = false
137 136
138 - #build visitor list
137 + #build visitor/option list
139 138 visitor_list = {}
139 + visitor_option_list = {}
140 140 while ARGV.length>0
141 141 key = ARGV.shift
142 142
143 143 case key
144 144 when '-d'
145 145 dry_run = true
146 146 when '-t'
147 147 num = ARGV.shift.to_i
148 148 load_time = num
149 149 else
150 - num = ARGV.shift.to_i
151 - visitor_list[key] = num
150 + if key =~ /--(\w+)=(.*)/
151 + # options
152 + lm = Regexp.last_match
153 + visitor_option_list[lm[1]] = lm[2]
154 + else
155 + # new visitor
156 + num = ARGV.shift.to_i
157 + visitor_list[key] = num
158 + end
152 159 end
153 160 end
154 161
162 + VISITOR_OPTION_LIST = visitor_option_list
163 + require visitor_file
164 +
155 165 initialize_temp_dir
156 166 runner visitor_list, load_time, {:dry_run => dry_run}
157 167
@@ -27,259 +27,266
27 27
28 28 class << self
29 29 attr_accessor :commands
30 30 attr_accessor :base_url
31 31 attr_accessor :cookies_stored
32 32 end
33 33
34 34 def get_cookie_fname
35 35 "#{@base_dir}/cookies.#{@id}"
36 36 end
37 37
38 38 def get_output_fname
39 39 "#{@base_dir}/output.#{@id}"
40 40 end
41 41
42 42 def id
43 43 @id
44 44 end
45 45
46 46 def initialize(id=0, base_dir='.')
47 47 # initialize nil class variable
48 48 self.class.base_url = "" if (self.class.base_url) == nil
49 49 self.class.cookies_stored = false if self.class.cookies_stored == nil
50 50
51 51 @id = id
52 52 @base_dir = base_dir
53 53 @cookies_fname = get_cookie_fname
54 54 @output_fname = get_output_fname
55 55 @statistics = Array.new
56 56 @talkative = false
57 57
58 58 @stopped = false
59 59 end
60 60
61 61 def cleanup
62 62 trial = 0
63 63 while FileTest.exists?(@cookies_fname)
64 64 File.delete(@cookies_fname)
65 65 if FileTest.exists?(@cookies_fname)
66 66 # wait until system returns
67 67 puts "STILL HERE"
68 68 sleep 1
69 69 trial += 1
70 70 break if trial>10
71 71 end
72 72 end
73 73
74 74 while FileTest.exists?(@output_fname)
75 75 File.delete(@output_fname)
76 76 if FileTest.exists?(@output_fname)
77 77 # wait until system returns
78 78 sleep 1
79 79 trial += 1
80 80 break if trial>10
81 81 end
82 82 end
83 83 end
84 84
85 85 def self.site_url(url)
86 86 self.base_url = url
87 87 end
88 88
89 89 def self.stores_cookies
90 90 self.cookies_stored = true
91 91 end
92 92
93 93 def self.preprocess_param_hash(params)
94 94 return {} if params==nil
95 95 plist = {}
96 96 params.each do |key,val|
97 97 if key.is_a? Symbol
98 98 key_s = key.to_s
99 99 else
100 100 key_s = key
101 101 end
102 102 plist[key_s] = val
103 103 end
104 104 plist
105 105 end
106 106
107 107 def self.get(url,params=nil)
108 108 self.commands = [] if self.commands==nil
109 109 self.commands << {
110 110 :command => :get,
111 111 :url => url,
112 112 :params => Visitor.preprocess_param_hash(params) }
113 113 end
114 114
115 115 def self.post(url,params=nil,options=nil)
116 116 self.commands = [] if self.commands==nil
117 117 self.commands << { :command => :post,
118 118 :url => url,
119 119 :params => Visitor.preprocess_param_hash(params),
120 120 :options => options }
121 121 end
122 122
123 + def self.process_options(options)
124 + if options.has_key? "site_url"
125 + self.base_url = options["site_url"]
126 + end
127 + end
128 +
123 129 def substitute_id(st)
124 130 return st if !(st.is_a? String)
125 131 st.gsub(/(()|(\$))\$\{id\}/) do |s|
126 132 if s=="${id}"
127 133 @id.to_s
128 134 else
129 135 "${id}"
130 136 end
131 137 end
132 138 end
133 139
134 140 def encode_params(params)
135 141 enc = ""
136 142 if params!=nil and params.length!=0
137 143 params.each do |key,val|
138 144 if enc != ""
139 145 enc += '&'
140 146 end
141 147 val = substitute_id(val)
142 148 enc += URI.escape(key) + '=' + URI.escape(val.to_s)
143 149 end
144 150 end
145 151 enc
146 152 end
147 153
148 154 def get(url,params)
149 155 #build url
150 156
151 157 #puts "----------------------cookies-----------"
152 158 #system("cat #{@cookies_fname}")
153 159 #puts "----------------------cookies-----------"
154 160
155 161 full_url = "#{self.class.base_url}#{url}"
156 162 if params!=nil and params.length!=0
157 163 full_url += '?' + encode_params(params)
158 164 end
159 165
160 166 cmd = "curl -k -b #{@cookies_fname} -D #{@cookies_fname} #{full_url} " +
161 167 " -s -L -o #{@output_fname}"
162 168 #puts ">>>>>>>>>>>>>>>>>> " + cmd
163 169 system(cmd)
164 170 #system("cat #{@output_fname}")
165 171 end
166 172
167 173 def post(url,params,options)
168 174 #puts "----------------------cookies-----------"
169 175 #system("cat #{@cookies_fname}")
170 176 #puts "----------------------cookies-----------"
171 177
172 178 full_url = "#{self.class.base_url}#{url}"
173 179 params_str = ""
174 180 if options!=nil and options[:multipart]==true
175 181 params.each do |key,val|
176 182 if val.is_a? Hash
177 183 case val[:type]
178 184 when :file
179 185 dval = substitute_id(val[:data])
180 186 params_str += " -F \"#{key}=@#{dval.to_s}\""
181 187 end
182 188 else
183 189 val = substitute_id(val)
184 190 params_str += " -F \"#{key}=#{URI.escape(val.to_s)}\""
185 191 end
186 192 end
187 193 else
188 194 params_str += "-d \"#{encode_params(params)}\""
189 195 end
190 196
191 197 #puts params_str
192 198
193 199 cmd = "curl -L -k -b #{@cookies_fname} -D #{@cookies_fname} " +
194 200 " #{params_str} #{full_url} -s -o #{@output_fname}"
195 201 #puts ">>>>>>>>>>>>>>>>>>>>>>>>>>> POST: " + cmd
196 202 system(cmd)
197 203 #system("cat #{@output_fname}")
198 204 end
199 205
200 206 def stop!
201 207 @stopped = true
202 208 end
203 209
204 210 def run(times=nil, options={})
205 211 times = 1 if times == :once
206 212
207 213 @stopped = false
208 214 while times!=0
209 215 self.class.commands.each do |cmd|
210 216 puts "#{@id}: #{cmd[:command]} #{cmd[:url]}" if @talkative
211 217
212 218 start_time = Time.new
213 219
214 220 if !options[:dry_run]
215 221 case cmd[:command]
216 222 when :get
217 223 get cmd[:url], cmd[:params]
218 224 when :post
219 225 post cmd[:url], cmd[:params], cmd[:options]
220 226 end
221 227 end
222 228
223 229 finish_time = Time.new
224 230
225 231 break if @stopped
226 232
227 233 @statistics << {
228 234 :url => "#{cmd[:command]}:#{cmd[:url]}",
229 235 :time => finish_time - start_time }
230 236 end
231 237
232 238 times -= 1 if times.is_a? Integer #otherwise, run forever
233 239
234 240 break if @stopped
235 241 end
236 242 end
237 243
238 244 def show_raw_stat
239 245 @statistics.each do |stat|
240 246 puts "#{stat[:url]} => #{stat[:time]}"
241 247 end
242 248 end
243 249
244 250 def statistics
245 251 num_requested = @statistics.length
246 252 totaltime = 0.0
247 253 @statistics.each { |stat| totaltime += stat[:time] }
248 254
249 255 if num_requested>0
250 256 average_request_time = totaltime / num_requested
251 257 else
252 258 average_request_time = 0
253 259 end
254 260
255 261 sq_sum = 0.0
256 262 @statistics.each do |stat|
257 263 sq_sum += (stat[:time]-average_request_time) ** 2
258 264 end
259 265 if num_requested>1
260 266 sd = Math.sqrt(sq_sum/(num_requested-1))
261 267 else
262 268 sd = 0
263 269 end
264 270
265 271 return {
266 272 :num_requested => num_requested,
267 273 :avg_request_time => average_request_time,
268 274 :std_dev => sd
269 275 }
270 276 end
271 277 end
272 278
273 - def visitor(cname,&blk)
279 + def visitor(cname,options={},&blk)
274 280 c = Class.new(Visitor)
275 281 begin
276 282 Object.const_set(cname,c)
277 283 rescue NameError
278 284 puts <<ERROR
279 285 Error on type #{cname}.
280 286 Type name should be capitalized and follow Ruby constant naming rule.
281 287 ERROR
282 288 exit(0)
283 289 end
290 + c.process_options(options)
284 291 c.instance_eval(&blk)
285 292 end
deleted file
You need to be logged in to leave comments. Login now