Skip to content

Commit

Permalink
Update aggregation performance tests
Browse files Browse the repository at this point in the history
- Allow more customization in the test runner by setting the measure
mode and number of runs through the environment (using the
PROFILE_NUM_RUNS and RUBY_PROF_MEASURE_MODE vars - see the RubyProf
documentation for the latter).
- Save reports in ./prof/{test_name} by default
- Print current state during tests instead of all at the end. Makes it
easier to verify what's currently happening, such as whether we are on
setup, teardown, or which run
- Insert TreeMetricResults in bulk, using the activerecord-import gem
  • Loading branch information
danielkza committed Jul 17, 2016
1 parent babd386 commit 167e3ac
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 60 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# Ignore all logfiles and tempfiles.
/log/*.log
/tmp
/prof

# Backup files
*~
Expand All @@ -23,4 +24,4 @@ config/repositories.yml
config/database.yml
features/support/kalibro_cucumber_helpers.yml
coverage
.capistrano
.capistrano
9 changes: 7 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ gem 'kolekti_metricfu', github: 'mezuro/kolekti_metricfu', branch: 'stable'
gem 'unparser', '< 0.2.5'
gem 'kolekti_radon', github: 'mezuro/kolekti_radon', branch: 'stable'

# Some statistics
gem 'descriptive-statistics', '~> 2.1.2'

# Bulk SQL inserts
gem 'activerecord-import'

group :test do
# Easier test writing
gem "shoulda-matchers", '~>2.8.0'
Expand Down Expand Up @@ -103,8 +109,7 @@ group :cucumber do
# gem 'database_cleaner' # Removed because it is getting added above.
end

# Some statistics
gem 'descriptive-statistics', '~> 2.1.2'


# Use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
Expand Down
5 changes: 4 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ GEM
activemodel (= 4.2.4)
activesupport (= 4.2.4)
arel (~> 6.0)
activerecord-import (0.15.0)
activerecord (>= 3.2)
activesupport (4.2.4)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
Expand Down Expand Up @@ -386,6 +388,7 @@ PLATFORMS
ruby

DEPENDENCIES
activerecord-import
byebug
capistrano (~> 3.4.0)
capistrano-bundler
Expand Down Expand Up @@ -424,4 +427,4 @@ DEPENDENCIES
unparser (< 0.2.5)

BUNDLED WITH
1.12.4
1.12.5
84 changes: 49 additions & 35 deletions performance/base.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
require 'fileutils'
require 'database_cleaner'
require 'kalibro_client/kalibro_cucumber_helpers'

module Performance
class Base
def initialize
@results = {}
def initialize(num_runs: nil, measure_mode: nil, save_reports: true)
if num_runs.nil?
num_runs = ENV.key?('PROFILE_NUM_RUNS') ? ENV['PROFILE_NUM_RUNS'].to_i : 1
end

@num_runs = num_runs
@measure_mode = measure_mode
@save_reports = save_reports
@results = []
end

def setup
Expand All @@ -21,56 +29,62 @@ def teardown
def subject; raise NotImplementedError; end

def run
self.run_process_time
self.run_wall_time

self.print
end
STDERR.puts "Profiling #{self.class.name}"

protected

def run_wall_time
self.setup
if @measure_mode
RubyProf.measure_mode = RubyProf.const_get(@measure_mode)
end

RubyProf.measure_mode = RubyProf::WALL_TIME
@results = (1..@num_runs).map do |i|
STDERR.puts "Setup: start"
self.setup
STDERR.puts "Setup: finish"

@results['Wall Time'] = []
(1..5).each do |it|
@results['Wall Time'] << RubyProf.profile do
STDERR.puts "Run #{i}: start"
prof = RubyProf.profile do
self.subject
end
STDERR.puts "Run #{i}: finish"

STDERR.puts "Teardown: start"
self.teardown
STDERR.puts "Teardown: finish"

prof
end

self.teardown
self.save_reports if @save_reports
self.print
end

def run_process_time
self.setup
protected

RubyProf.measure_mode = RubyProf::PROCESS_TIME
def print
puts "#{@measure_mode.to_s}:"

@results['Process Time'] = []
(1..5).each do |it|
@results['Process Time'] << RubyProf.profile do
self.subject
end
if RubyProf.measure_mode == RubyProf::WALL_TIME
totals = @results.map { |r| r.threads.map(&:total_time).max }
else
totals = @results.map { |r| r.threads.map(&:total_time).reduce(:+) }
end

self.teardown
end

def print
puts "\n"
puts "#{self.class.name}\n----------"
totals.each do |time|
puts " #{time}"
end

@results.each do |title, result|
total = 0.0
puts " Average: #{totals.reduce(:+) / @results.count}"
puts
end

result.each { |r| r.threads.each { |thread| total += thread.total_time} }
def save_reports
path = "prof/#{self.class.name}"
FileUtils.mkdir_p(path)
base_prof = Time.now.strftime('%Y-%m-%d_%H-%M-%S')

puts "* #{title}: #{total/result.count}"
@results.each_with_index do |result, i|
printer = RubyProf::MultiPrinter.new(result)
printer.print(path: path, profile: "#{base_prof}_#{i}")
end
puts "\n"
end
end
end
40 changes: 19 additions & 21 deletions performance/tests/aggregation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def setup
FactoryGirl.create(:metric_configuration, metric: FactoryGirl.build(:lines_of_code_metric, code: 'pyloc'), id: nil, kalibro_configuration_id: kalibro_configuration.id)
]
code_dir = "/tmp/test"

repository = FactoryGirl.create(:repository, scm_type: "GIT", kalibro_configuration: kalibro_configuration, code_directory: code_dir)
root_module_result = FactoryGirl.create(:module_result,
id: nil, processing: nil,
Expand All @@ -32,37 +33,34 @@ def setup
Processor::Preparer.metrics_list(@context)

previous_module_results = [root_module_result]
(0..(TREE_HEIGHT - 2)).each do # The first level is the ROOT
next_module_results = []
ModuleResult.transaction do
(0..(TREE_HEIGHT - 2)).each do # The first level is the ROOT
next_module_results = []

previous_module_results.each do |parent|
(0..(TREE_WIDTH - 1)).each do
next_module_results << FactoryGirl.create(:module_result,
id: nil,
processing: processing,
parent: parent,
tree_metric_results: [],
hotspot_metric_results: [])
FactoryGirl.create(:kalibro_module_with_package_granularity,
module_result: next_module_results.last,
long_name: [*('a'..'z'),*('0'..'9')].shuffle[0,8].join # random unique name
)
previous_module_results.each do |parent|
(0..(TREE_WIDTH - 1)).each do
next_module_results << ModuleResult.create!(processing: processing,
parent_id: parent.id)
FactoryGirl.create(:kalibro_module_with_package_granularity,
module_result: next_module_results.last,
long_name: [*('a'..'z'),*('0'..'9')].shuffle[0,8].join # random unique name
)
end
end
end

previous_module_results = next_module_results
previous_module_results = next_module_results
end
end

tree_metric_results = []
previous_module_results.each do |module_result|
metric_configurations.each do |metric_configuration|
FactoryGirl.create(:tree_metric_result,
module_result: module_result,
metric_configuration: metric_configuration,
metric: metric_configuration.metric,
value: rand)
tree_metric_results << [module_result.id, metric_configuration.id, rand]
end
end

TreeMetricResult.import([:module_result_id, :metric_configuration_id, :value], tree_metric_results)

puts "Done creating #{ModuleResult.count} ModuleResults and #{MetricResult.count} MetricResults that will get aggregated following"
end

Expand Down

0 comments on commit 167e3ac

Please sign in to comment.