# # This file is part of a web load testing tool (currently having no name) # Copyright (C) 2008 Jittat Fakcharoenphol # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # require 'visitor_curl_cli' TEMP_DIR = './tmp' def show_usage puts < [ ] [ ] ... [options] * visitor_file : your visitor definition file, (with or without .rb) * type, number : the type and the number of visitors of that type * options : any of the following -t specify how long (in seconds) -d dry-run: run, but make no real http requests USAGE end def initialize_temp_dir if !FileTest.exists? TEMP_DIR Dir.mkdir TEMP_DIR end end def runner(visitor_lists, load_time=60, options={}) visitors = [] vcount = 0 visitor_lists.each do |cname, num| begin c = Kernel.const_get(cname) num.times do visitors[vcount] = c.new(vcount+1, TEMP_DIR) visitors[vcount].talkative = true vcount += 1 end rescue NameError puts "Can't find class #{cname}" show_usage exit(0) end end puts "Having #{vcount} visitors" vthread = [] all_start_time = Time.new # start all visitors vcount.times do |i| vthread[i] = Thread.new do visitors[i].run(:forever,options) end end # wait for load_time seconds sleep load_time visitors.each do |visitor| visitor.stop! end all_finish_time = Time.new begin # wait for all threads to stop vcount.times do |i| #puts "Waiting for thread #{i}, #{vthread[i].alive?}" vthread[i].join end rescue Interrupt # kill all remaining threads vcount.times do |i| vthread[i].kill if vthread[i].alive? end end # clean up visitors.each do |visitor| #puts "Clean up: #{visitor.id}" visitor.cleanup end #all_finish_time = Time.new total_req = 0 vcount.times do |i| stat = visitors[i].statistics # puts "TYPE: #{visitors[i].class}" # puts "Total requested = #{stat[:num_requested]}" # puts "Average = #{stat[:avg_request_time]}" # puts "S.D. = #{stat[:std_dev]}" total_req += stat[:num_requested] end elapsed_time = all_finish_time - all_start_time puts puts "Total time = #{elapsed_time} sec." puts "Total requests = #{total_req}" puts "Trans. per sec = #{total_req/elapsed_time}" end ########################### # MAIN ########################### if ARGV.length==0 show_usage exit(0) end visitor_file = ARGV.shift load_time = 60 dry_run = false #build visitor/option list visitor_list = {} visitor_option_list = {} while ARGV.length>0 key = ARGV.shift case key when '-d' dry_run = true when '-t' num = ARGV.shift.to_i load_time = num else if key =~ /--(\w+)=(.*)/ # options lm = Regexp.last_match visitor_option_list[lm[1]] = lm[2] else # new visitor num = ARGV.shift.to_i visitor_list[key] = num end end end VISITOR_OPTION_LIST = visitor_option_list require visitor_file initialize_temp_dir runner visitor_list, load_time, {:dry_run => dry_run}