1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
# frozen_string_literal: true
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|
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 )
tms = nil
puts "Benchmarking #{description}"
Benchmark.bm { |x| tms = x.report { yield } }
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 ) do
vals.each do |values|
model_clazz.create create_hash_for_cols_and_vals( cols, values )
end
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|
if subclass.table_exists? && subclass.respond_to?(:delete_all)
subclass.delete_all
end
end
end
def initialize # :nodoc:
@results = []
end
end
|