class RubybenchRunner::BaseRunner
Constants
- COPY_FOLDERS
- DEFAULT_OPTS
- HELPERS_VERSION_FILE
Attributes
opts[R]
repo_path[R]
script_url[R]
Public Class Methods
new(script, opts = {})
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 33 def initialize(script, opts = {}) @script_name = script @opts = OpenStruct.new(DEFAULT_OPTS.merge(opts)) @script_url = @opts.url || script_full_url(script) @results = [] @error = nil @output = "" end
Public Instance Methods
benchmark_name()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 137 def benchmark_name raise "Override the `benchmark_name` method in your class" end
bundle_install()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 259 def bundle_install return if without_bundle? log("Installing gems...") comm = "bundle install" if opts.db == "mysql2" comm += " --without postgres" elsif opts.db == "postgres" comm += " --without mysql" else comm += " --without mysql postgres" end comm += " > /dev/null 2>&1" if !opts.verbose Dir.chdir(File.dirname(gemfile_location)) do system(comm) end if require_db? Dir.chdir(File.join(dest_dir, "support", "setup")) do system(comm) end end end
check_dependencies()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 145 def check_dependencies return if opts.skip_dependencies_check || !require_db? if opts.db == "postgres" require_gem 'pg' elsif opts.db == "mysql2" require_gem 'mysql2' end log("Checking dependencies...") RubybenchRunner::DependenciesChecker.check(pg: opts.db == "postgres", mysql: opts.db == "mysql2") end
command()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 129 def command if without_bundle? "ruby #{script_name}" else "BUNDLE_GEMFILE=#{gemfile_location} bundle exec ruby #{script_name}" end end
copy_helpers(dest)
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 95 def copy_helpers(dest) gem_helpers_version_path = File.join(__dir__, HELPERS_VERSION_FILE) current_helpers_version_path = File.join(dest, HELPERS_VERSION_FILE) if !File.exists?(current_helpers_version_path) || File.read(gem_helpers_version_path) != File.read(current_helpers_version_path) FileUtils.cp(gem_helpers_version_path, current_helpers_version_path) COPY_FOLDERS.each do |folder| origin = File.join(__dir__, folder) destination = File.join(dest, folder) FileUtils.cp_r(origin, destination) end end end
create_tmpdir()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 90 def create_tmpdir FileUtils.mkdir_p(dest_dir) copy_helpers(dest_dir) end
dest_dir()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 85 def dest_dir # directory where all helpers and gems will be installed/copied to @dest_dir ||= File.join(Dir.tmpdir, "rubybench_runner_tmp") end
download_script()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 283 def download_script log("Downloading script...") content = open(script_url).read File.write(script_full_path, content) rescue OpenURI::HTTPError => e log("Script download failed #{script_url}", f: true) @error = e end
gemfile_content()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 113 def gemfile_content nil end
is_repo_path_valid?()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 62 def is_repo_path_valid? true end
possible_repo_path()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 58 def possible_repo_path File.join(Dir.home, benchmark_name.downcase) end
print_results()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 228 def print_results if @error @output = <<~OUTPUT An error occurred while running the benchmarks: Error #{@error.class}: #{@error.message} Backtrace: #{@error.backtrace.join("\n")} OUTPUT if @results.size > 0 @output += <<~OUTPUT ------ Raw results until this error: #{@results} OUTPUT end else label = @results.first['label'] version = @results.first['version'] @output = "#{benchmark_name} version #{version}\n" @output += "Results (#{@results.size} runs):\n" @results.map!.with_index do |res, ind| res.delete('label') res.delete('version') { "run #{ind + 1}" => res } end @output += "\n" @output += @results.to_yaml.sub("---\n", "") end puts @output end
process_results()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 212 def process_results return if @error @results.map! do |res| res.each do |key, val| if Float === val res[key] = val.round(opts.round) end end res end @results.sort_by! do |res| res['iterations_per_second'] end end
require_db?()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 141 def require_db? false end
run()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 42 def run set_repo_path cleanup(before: true) create_tmpdir check_dependencies write_gemfile bundle_install setup_db download_script run_benchmarks process_results print_results ensure cleanup(after: true) end
run_benchmarks()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 194 def run_benchmarks return if @error log("Running benchmarks...") Dir.chdir(script_path) do opts.repeat_count.times do |n| res, err = Open3.capture3(command) if err.size == 0 @results[n] = res @results[n] = JSON.parse(res) else raise ShellError.new(err) end end end rescue => err @error = err end
save_dir()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 109 def save_dir raise "Override the `save_dir` method in your subclass #{self.class.name}" end
script_full_path()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 121 def script_full_path @script_full_path ||= File.join(script_path, script_name) end
script_name()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 125 def script_name "script.rb" end
script_path()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 117 def script_path @script_path ||= File.join(save_dir, "benchmarks") end
set_repo_path()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 66 def set_repo_path name = benchmark_name.downcase from_opts = false if path = opts.send(name) from_opts = true @repo_path = path else @repo_path = possible_repo_path log("Running #{name} benchmark #{@script_name}: #{name} path is #{possible_repo_path}\n") end unless is_repo_path_valid? output = "Cannot find #{name} at #{@repo_path}." output += "Perhaps try:\n\nrubybench_runner run #{name}/#{@script_name} --#{name}=/path/to/#{name}" unless from_opts log(output, f: true) exit 1 end end
setup_db()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 158 def setup_db return if !require_db? log("Checking database...") config = RubybenchRunner::Configurations.new(mysql_map: true) if opts.db == "postgres" conn_config = config["postgres"] rubybench_db = conn_config[:dbname] conn_config[:dbname] = "postgres" conn = PG.connect(conn_config) begin res = conn.exec("SELECT 1 FROM pg_database WHERE datname = '#{rubybench_db}'") if !res.first conn.exec("CREATE DATABASE #{rubybench_db}") log("Created PostgreSQL database with the name '#{rubybench_db}'") end ensure conn.close end elsif opts.db == "mysql2" conn_config = config["mysql2"] rubybench_db = conn_config[:database] conn_config[:database] = "mysql" client = Mysql2::Client.new(conn_config) begin res = client.query("SHOW DATABASES LIKE '#{rubybench_db}'") if !res.first client.query("CREATE DATABASE #{rubybench_db}") log("Created MySQL database with the name '#{rubybench_db}'") end ensure client.close end end end
write_gemfile()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 292 def write_gemfile return if without_bundle? File.write(gemfile_location, gemfile_content) end
Private Instance Methods
cleanup(before: false, after: false)
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 312 def cleanup(before: false, after: false) FileUtils.rm_f(script_full_path) FileUtils.rm_rf(dest_dir) if (opts.fresh_run && before) || (opts.cleanup && after) end
gemfile_location()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 308 def gemfile_location File.join(save_dir, "Gemfile") end
install_gem(gem_name)
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 345 def install_gem(gem_name) cmd = Gem::Commands::InstallCommand.new cmd.handle_options [gem_name] cmd.execute rescue Gem::SystemExitException => e puts "FAILURE: #{e.exit_code} -- #{e.message}" if e.exit_code != 0 end
log(msg, f: false)
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 299 def log(msg, f: false) return if opts.quiet && !f puts msg end
require_gem(gem_name)
click to toggle source
small hack for dynamically installing/requiring gems. some benchmarks don't require db at all so having mysql2 and pg in the gemspec file means everyone must have postgres and mysql installed on their machine in order to use this gem. this hack allows us to not require mysql/postgres until the user tries to run a benchmark that needs db. – source stackoverflow.com/a/36570445
# File lib/rubybench_runner/base_runner.rb, line 334 def require_gem(gem_name) require 'rubygems/commands/install_command' Gem::Specification::find_by_name(gem_name) rescue Gem::LoadError log("Installing the '#{opts.db}' gem...") install_gem(gem_name) ensure log("Using the '#{opts.db}' gem...") require gem_name end
script_full_url(script)
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 317 def script_full_url(script) if script !~ /\.rb$/ script += ".rb" end "https://raw.githubusercontent.com/ruby-bench/ruby-bench-suite/master/#{benchmark_name.downcase}/benchmarks/#{script}" end
without_bundle?()
click to toggle source
# File lib/rubybench_runner/base_runner.rb, line 304 def without_bundle? !gemfile_content end