138 lines
4.7 KiB
Ruby
138 lines
4.7 KiB
Ruby
|
class BenchmarkBase
|
||
|
|
||
|
attr_reader :results
|
||
|
|
||
|
# The main benchmark method dispatcher. This dispatches the benchmarks
|
||
|
# to actual benchmark_xxxx methods.
|
||
|
#
|
||
|
# == PARAMETERS
|
||
|
# * table_types - an array of table types to benchmark
|
||
|
# * num - the number of record insertions to test
|
||
|
def benchmark( table_types, num )
|
||
|
array_of_cols_and_vals = build_array_of_cols_and_vals( num )
|
||
|
table_types.each do |table_type|
|
||
|
self.send( "benchmark_#{table_type}", array_of_cols_and_vals )
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Returns an OpenStruct which contains two attritues, +description+ and +tms+ after performing an
|
||
|
# actual benchmark.
|
||
|
#
|
||
|
# == PARAMETERS
|
||
|
# * description - the description of the block that is getting benchmarked
|
||
|
# * blk - the block of code to benchmark
|
||
|
#
|
||
|
# == RETURNS
|
||
|
# An OpenStruct object with the following attributes:
|
||
|
# * description - the description of the benchmark ran
|
||
|
# * tms - a Benchmark::Tms containing the results of the benchmark
|
||
|
def bm( description, &blk )
|
||
|
tms = nil
|
||
|
puts "Benchmarking #{description}"
|
||
|
|
||
|
Benchmark.bm { |x| tms = x.report { blk.call } }
|
||
|
delete_all
|
||
|
failed = false
|
||
|
|
||
|
OpenStruct.new :description=>description, :tms=>tms, :failed=>failed
|
||
|
end
|
||
|
|
||
|
# Given a model class (ie: Topic), and an array of columns and value sets
|
||
|
# this will perform all of the benchmarks necessary for this library.
|
||
|
#
|
||
|
# == PARAMETERS
|
||
|
# * model_clazz - the model class to benchmark (ie: Topic)
|
||
|
# * array_of_cols_and_vals - an array of column identifiers and value sets
|
||
|
#
|
||
|
# == RETURNS
|
||
|
# returns true
|
||
|
def bm_model( model_clazz, array_of_cols_and_vals )
|
||
|
puts
|
||
|
puts "------ Benchmarking #{model_clazz.name} -------"
|
||
|
|
||
|
cols,vals = array_of_cols_and_vals
|
||
|
num_inserts = vals.size
|
||
|
|
||
|
# add a new result group for this particular benchmark
|
||
|
group = []
|
||
|
@results << group
|
||
|
|
||
|
description = "#{model_clazz.name}.create (#{num_inserts} records)"
|
||
|
group << bm( description ) {
|
||
|
vals.each do |values|
|
||
|
model_clazz.create create_hash_for_cols_and_vals( cols, values )
|
||
|
end }
|
||
|
|
||
|
description = "#{model_clazz.name}.import(column, values) for #{num_inserts} records with validations"
|
||
|
group << bm( description ) { model_clazz.import cols, vals, :validate=>true }
|
||
|
|
||
|
description = "#{model_clazz.name}.import(columns, values) for #{num_inserts} records without validations"
|
||
|
group << bm( description ) { model_clazz.import cols, vals, :validate=>false }
|
||
|
|
||
|
models = []
|
||
|
array_of_attrs = []
|
||
|
|
||
|
vals.each do |arr|
|
||
|
array_of_attrs << (attrs={})
|
||
|
arr.each_with_index { |value, i| attrs[cols[i]] = value }
|
||
|
end
|
||
|
array_of_attrs.each{ |attrs| models << model_clazz.new(attrs) }
|
||
|
|
||
|
description = "#{model_clazz.name}.import(models) for #{num_inserts} records with validations"
|
||
|
group << bm( description ) { model_clazz.import models, :validate=>true }
|
||
|
|
||
|
description = "#{model_clazz.name}.import(models) for #{num_inserts} records without validations"
|
||
|
group << bm( description ) { model_clazz.import models, :validate=>false }
|
||
|
|
||
|
true
|
||
|
end
|
||
|
|
||
|
# Returns a two element array composing of an array of columns and an array of
|
||
|
# value sets given the passed +num+.
|
||
|
#
|
||
|
# === What is a value set?
|
||
|
# A value set is an array of arrays. Each child array represents an array of value sets
|
||
|
# for a given row of data.
|
||
|
#
|
||
|
# For example, say we wanted to represent an insertion of two records:
|
||
|
# column_names = [ 'id', 'name', 'description' ]
|
||
|
# record1 = [ 1, 'John Doe', 'A plumber' ]
|
||
|
# record2 = [ 2, 'John Smith', 'A painter' ]
|
||
|
# value_set [ record1, record2 ]
|
||
|
#
|
||
|
# == PARAMETER
|
||
|
# * num - the number of records to create
|
||
|
def build_array_of_cols_and_vals( num )
|
||
|
cols = [ :my_name, :description ]
|
||
|
value_sets = []
|
||
|
num.times { |i| value_sets << [ "My Name #{i}", "My Description #{i}" ] }
|
||
|
[ cols, value_sets ]
|
||
|
end
|
||
|
|
||
|
# Returns a hash of column identifier to value mappings giving the passed in
|
||
|
# value array.
|
||
|
#
|
||
|
# Example:
|
||
|
# cols = [ 'id', 'name', 'description' ]
|
||
|
# values = [ 1, 'John Doe', 'A plumber' ]
|
||
|
# hsh = create_hash_for_cols_and_vals( cols, values )
|
||
|
# # hsh => { 'id'=>1, 'name'=>'John Doe', 'description'=>'A plumber' }
|
||
|
def create_hash_for_cols_and_vals( cols, vals )
|
||
|
h = {}
|
||
|
cols.zip( vals ){ |col,val| h[col] = val }
|
||
|
h
|
||
|
end
|
||
|
|
||
|
# Deletes all records from all ActiveRecord subclasses
|
||
|
def delete_all
|
||
|
ActiveRecord::Base.send( :subclasses ).each do |subclass|
|
||
|
subclass.delete_all if subclass.respond_to? :delete_all
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def initialize # :nodoc:
|
||
|
@results = []
|
||
|
end
|
||
|
|
||
|
end
|