#!/usr/bin/env ruby
# Simple benchmark to compare Thin performance against
# other webservers supported by Rack.
#
# Run with:
#
#  ruby simple.rb [num of request] [print|graph] [concurrency levels]
#

$: << File.join(File.dirname(__FILE__), '..', 'lib')
require 'thin'

require File.dirname(__FILE__) + '/benchmarker'
require 'optparse'

options = {
  :requests      => 1000,
  :concurrencies => [1, 10, 100],
  :keep_alive    => false,
  :output        => :table
}

OptionParser.new do |opts|
  opts.banner = "Usage: #{$PROGRAM_NAME} [options]"

  opts.on("-n", "--requests NUM", "Number of requests")         { |num| options[:requests] = num.to_i }
  opts.on("-c", "--concurrencies EXP", "Concurrency levels")    { |exp| options[:concurrencies] = eval(exp).to_a }
  opts.on("-k", "--keep-alive", "Use persistent connections")   { options[:keep_alive] = true }
  opts.on("-t", "--table", "Output as text table")              { options[:output] = :table }
  opts.on("-g", "--graph", "Output as graph")                   { options[:output] = :graph }
  
  opts.on_tail("-h", "--help", "Show this message")     { puts opts; exit }
end.parse!(ARGV)

# benchmark output_type, %w(WEBrick Mongrel EMongrel Thin), request, levels
b = Benchmarker.new
b.requests = options[:requests]
b.concurrencies = options[:concurrencies]
b.keep_alive = options[:keep_alive]

case options[:output]
when :table
  puts 'server     request   concurrency   req/s    failures'
  puts '=' * 52
  
  b.writer do |server, requests, concurrency, req_sec, failed|
    puts "#{server.ljust(8)}   #{requests}      #{concurrency.to_s.ljust(4)}          #{req_sec.to_s.ljust(8)} #{failed}"
  end
  
  b.run!

when :graph
  require '/usr/local/lib/ruby/gems/1.8/gems/gruff-0.2.9/lib/gruff'
  g = Gruff::Area.new
  g.title = "#{options[:requests]} requests"
  g.title << ' w/ Keep-Alive' if options[:keep_alive]
  
  g.x_axis_label  = 'Concurrency'
  g.y_axis_label  = 'Requests / sec'
  g.maximum_value = 0
  g.minimum_value = 0
  g.labels        = {}
  b.concurrencies.each_with_index { |c, i| g.labels[i] = c.to_s }
  
  results = {}
  
  b.writer do |server, requests, concurrency, req_sec, failed|
    print '.'
    results[server] ||= []
    results[server] << req_sec
  end
  
  b.run!
  puts
  
  results.each do |server, concurrencies|
    g.data(server, concurrencies)    
  end
  
  g.write('bench.png')
  `open bench.png`
end
