Created
October 12, 2009 19:14
-
-
Save joewilliams/208651 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# a script to perform httperf tests on couchdb | |
# requires the gems below as well as httperf | |
# some of the code was taken from http://github.com/sv/httperf4r | |
# set "ulimit -n 65535" | |
# change FD_SET_SIZE to 65535 in /usr/include/bits/typesizes.h before compiling httperf | |
require 'rubygems' | |
require 'rest_client' | |
require 'json' | |
require 'open4' | |
include Open4 | |
HOST="localhost" | |
PORT="5984" | |
DB="testdb" | |
SESSIONS="500" | |
RATE="200" | |
DOC_SIZE = 100 # bytes | |
WRITES = 1 | |
READS = 1 | |
def create_write_wsesslog | |
# create some random data for the doc writes | |
chars = ('a'..'z').to_a + ('A'..'Z').to_a | |
doc = (0...DOC_SIZE).collect { chars[rand(chars.length)] }.join | |
# create the httperf wsesslog file | |
filename = "httperf_write_wsesslog_#{Time.now.to_i}" | |
write_wsesslog = File.new(filename, "w") | |
(1..WRITES).each do |write| | |
write_wsesslog.puts "/#{DB}/ method=POST contents=\'{\"field\": \"#{doc}\"}\'" | |
end | |
write_wsesslog.close | |
filename | |
end | |
def create_read_wsesslog | |
# parse _all_docs to get all the doc ids for reads | |
all_docs = RestClient.get("http://#{HOST}:#{PORT}/#{DB}/_all_docs?limit=#{READS}") | |
all_docs_json = JSON.parse(all_docs) | |
# create the httperf wsesslog file | |
filename = "httperf_read_wsesslog_#{Time.now.to_i}" | |
read_wsesslog = File.new(filename, "w") | |
all_docs_json["rows"].each do |row| | |
read_wsesslog.puts "/#{DB}/#{row["id"]} method=GET" | |
end | |
read_wsesslog.close | |
filename | |
end | |
def run_httperf(wsesslog) | |
# run httperf with the wsesslog and write results to file | |
httperf_cmd = <<-EOH | |
/usr/local/bin/httperf \ | |
--hog \ | |
--rate=#{RATE} \ | |
--timeout=5 \ | |
--send-buffer=4096 \ | |
--recv-buffer=16384 \ | |
--max-connections=4 \ | |
--max-piped-calls=32 \ | |
--server=#{HOST} \ | |
--port=#{PORT} \ | |
--wsesslog=#{SESSIONS},0,#{wsesslog} | |
EOH | |
results = "" | |
status = popen4(httperf_cmd) do |pid, stdin, stdout, stderr| | |
stdout.each do |line| | |
results << line | |
end | |
end | |
results | |
end | |
def parse_results(output) | |
results={} | |
output.each_line{ |line| | |
#puts line | |
results['replies']=$1.to_i if line=~/^Total: .*replies (\d+)/ | |
results['con_rate']=$1 if line=~/^Connection rate: (\d+\.\d)/ | |
results['req_rate']=$1 if line=~/^Request rate: (\d+\.\d)/ | |
if line=~/^Reply rate .* min (\d+\.\d) avg (\d+\.\d) max (\d+\.\d) stddev (\d+\.\d)/ | |
results['rep_rate_min']=$1 | |
results['rep_rate_avg']=$2 | |
results['rep_rate_max']=$3 | |
results['rep_rate_stddev']=$4 | |
end | |
results['rep_time']=$1 if line=~/^Reply time .* response (\d+\.\d)/ | |
results['net_io']=$1 if line=~/^Net I\/O: (\d+\.\d)/ | |
results['errors']=$1 if line=~/^Errors: total (\d+)/ | |
} | |
if results['replies']==0 | |
puts "Zero replies recieved,test invalid: rate #{results['rate']}\n" | |
else | |
results['percent_errors']=(100*results['errors'].to_f/results['replies'].to_f).to_s | |
end | |
results | |
end | |
def format_results(results) | |
line="" | |
header=['req_rate','con_rate','rep_rate_min','rep_rate_avg','rep_rate_max', | |
'rep_rate_stddev', 'rep_time','net_io','percent_errors'] | |
header.each{|h| line << "#{h}\t"} | |
line << "\n" | |
header.each{|h|line << results[h] << "\t"} | |
line<<"\n" | |
end | |
def main | |
puts "benchmark configuration:" | |
puts <<-EOH | |
Host: #{HOST} | |
Port: #{PORT} | |
DB: #{DB} | |
Sessions: #{SESSIONS} | |
Rate: #{RATE} | |
Document Size: #{DOC_SIZE} | |
Writes per session: #{WRITES} | |
Reads per session: #{READS} | |
EOH | |
puts "####################\n\n" | |
# create the db | |
RestClient.put("http://#{HOST}:#{PORT}/#{DB}", "") | |
# run the writes first | |
puts "running write test ..." | |
puts "####################\n" | |
write_wsesslog = create_write_wsesslog | |
results = run_httperf(write_wsesslog) | |
output = parse_results(results) | |
puts format_results(output) | |
sleep 120 | |
# now the reads | |
puts "\n\n" | |
puts "running read test ..." | |
puts "####################\n" | |
read_wsesslog = create_read_wsesslog | |
results = run_httperf(read_wsesslog) | |
output = parse_results(results) | |
puts format_results(output) | |
# clean up | |
RestClient.delete("http://#{HOST}:#{PORT}/#{DB}") | |
end | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment