Skip to content

Instantly share code, notes, and snippets.

@joewilliams
Created October 12, 2009 19:14
Show Gist options
  • Save joewilliams/208651 to your computer and use it in GitHub Desktop.
Save joewilliams/208651 to your computer and use it in GitHub Desktop.
# 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