module BigBench
# Holds the actual benchmark methods. A benchmark is a sequence of requests to the same server, but to different paths.
# A testrun can consist of multiple benchmarks like this:
#
# benchmark "default website pages" => "http://localhost:3000" do
# get "/"
# get "/blog"
# get "/imprint"
# get "/admin", :basic_auth => ['admin', 'secret']
# end
#
# benchmark "login and logout" => "http://localhost:3000" do
# post "/login", :params => { :name => "test@user.com", :password => "secret" }
# post "/logout", :params => { :name => "test@user.com" }
# end
#
# Those benchmarks automatically get added to the modules benchmark array and can be retrieved with the BigBench#benchmarks method.
module Benchmark
@benchmarks = []
class Benchmark
attr_accessor :name
attr_accessor :uri
attr_accessor :users
attr_accessor :duration
attr_accessor :fragments
attr_accessor :tracker
attr_accessor :start
attr_accessor :is_running
attr_accessor :runs
# Initizalizes a new benchmark
def initialize(name, url, options, &block)
@name, @uri, @tracker, @is_running, @runs = name, URI(url), Tracker::Tracker.new, false, 0
@users = options[:users] || BigBench.config.users
@duration = options[:duration] || BigBench.config.duration
@fragments = BigBench::Fragment.parse(self, &block)
end
# Execute this benchmark
def run!
# Setup Timer
timer = Thread.new{ sleep(@duration); @is_running = false }
@start, @is_running = Time.now, true
# Loop Requests
@users.times { Looper.new(self).loop! }
@runs += 1
end
# Returns if this benchmark is currently running
def is_running?
@is_running
end
end
# Adds a benchmark to the BigBench module. It can later be retrieved with the all method.
def self.add(options, &block)
name, url = options.select{ |key, value| true unless key.is_a?(Symbol) }.first
benchmark = Benchmark.new(name, url, options, &block)
@benchmarks << benchmark
benchmark
end
# Returns all benchmarks that are registered
def self.all
@benchmarks
end
# Resets all benchmarks
def self.reset!
@benchmarks = []
end
# Returns the longest duration of all benchmarks
def self.max_duration
all.map{ |benchmark| benchmark.duration }.max
end
end
# Add a benchmark like this:
#
# benchmark "default website pages" => "http://localhost:3000" do
# get "/"
# get "/blog"
# get "/imprint"
# get "/admin", :basic_auth => ['admin', 'secret']
# end
#
# benchmark "login and logout" => "http://localhost:3000" do
# post "/login", :params => { :name => "test@user.com", :password => "secret" }
# post "/logout", :params => { :name => "test@user.com" }
# end
#
def self.benchmark(options)
return unless block_given?
Benchmark.add(options, &Proc.new)
end
# List all available benchmarks
def self.benchmarks
Benchmark.all
end
# Returns the duration of all benchmarks - ergo the duration of the longest one
def self.duration
Benchmark.max_duration
end
end