Skip to content

Commit f9ce1d3

Browse files
authored
Merge pull request #440 from ruby/rmf-outputs
Move the methods to prepare the benchmark outputs to the BenchmarkRunner class
2 parents c43731e + 5b3a1e1 commit f9ce1d3

File tree

4 files changed

+474
-112
lines changed

4 files changed

+474
-112
lines changed

lib/benchmark_runner.rb

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,105 @@
33
require 'csv'
44
require 'json'
55
require 'rbconfig'
6+
require_relative 'table_formatter'
67

78
# Extracted helper methods from run_benchmarks.rb for testing
89
module BenchmarkRunner
9-
module_function
10+
class << self
11+
# Determine output path - either use the override or find a free file number
12+
def output_path(out_path_dir, out_override: nil)
13+
if out_override
14+
out_override
15+
else
16+
# If no out path is specified, find a free file index for the output files
17+
file_no = free_file_no(out_path_dir)
18+
File.join(out_path_dir, "output_%03d" % file_no)
19+
end
20+
end
1021

11-
# Find the first available file number for output files
12-
def free_file_no(directory)
13-
(1..).each do |file_no|
14-
out_path = File.join(directory, "output_%03d.csv" % file_no)
15-
return file_no unless File.exist?(out_path)
22+
# Write benchmark data to JSON file
23+
def write_json(output_path, ruby_descriptions, bench_data)
24+
out_json_path = "#{output_path}.json"
25+
out_data = {
26+
metadata: ruby_descriptions,
27+
raw_data: bench_data,
28+
}
29+
File.write(out_json_path, JSON.generate(out_data))
30+
out_json_path
1631
end
17-
end
1832

19-
# Render a graph from JSON benchmark data
20-
def render_graph(json_path)
21-
png_path = json_path.sub(/\.json$/, '.png')
22-
require_relative 'graph_renderer'
23-
GraphRenderer.render(json_path, png_path)
24-
end
33+
# Write benchmark results to CSV file
34+
def write_csv(output_path, ruby_descriptions, table)
35+
out_csv_path = "#{output_path}.csv"
36+
37+
CSV.open(out_csv_path, "wb") do |csv|
38+
ruby_descriptions.each do |key, value|
39+
csv << [key, value]
40+
end
41+
csv << []
42+
table.each do |row|
43+
csv << row
44+
end
45+
end
46+
47+
out_csv_path
48+
end
49+
50+
# Build output text string with metadata, table, and legend
51+
def build_output_text(ruby_descriptions, table, format, bench_failures)
52+
base_name, *other_names = ruby_descriptions.keys
53+
54+
output_str = +""
55+
56+
ruby_descriptions.each do |key, value|
57+
output_str << "#{key}: #{value}\n"
58+
end
2559

26-
# Checked system - error or return info if the command fails
27-
def check_call(command, env: {}, raise_error: true, quiet: false)
28-
puts("+ #{command}") unless quiet
60+
output_str << "\n"
61+
output_str << TableFormatter.new(table, format, bench_failures).to_s + "\n"
2962

30-
result = {}
63+
unless other_names.empty?
64+
output_str << "Legend:\n"
65+
other_names.each do |name|
66+
output_str << "- #{name} 1st itr: ratio of #{base_name}/#{name} time for the first benchmarking iteration.\n"
67+
output_str << "- #{base_name}/#{name}: ratio of #{base_name}/#{name} time. Higher is better for #{name}. Above 1 represents a speedup.\n"
68+
end
69+
end
3170

32-
result[:success] = system(env, command)
33-
result[:status] = $?
71+
output_str
72+
end
3473

35-
unless result[:success]
36-
puts "Command #{command.inspect} failed with exit code #{result[:status].exitstatus} in directory #{Dir.pwd}"
37-
raise RuntimeError.new if raise_error
74+
# Render a graph from JSON benchmark data
75+
def render_graph(json_path)
76+
png_path = json_path.sub(/\.json$/, '.png')
77+
require_relative 'graph_renderer'
78+
GraphRenderer.render(json_path, png_path)
3879
end
3980

40-
result
81+
# Checked system - error or return info if the command fails
82+
def check_call(command, env: {}, raise_error: true, quiet: false)
83+
puts("+ #{command}") unless quiet
84+
85+
result = {}
86+
87+
result[:success] = system(env, command)
88+
result[:status] = $?
89+
90+
unless result[:success]
91+
puts "Command #{command.inspect} failed with exit code #{result[:status].exitstatus} in directory #{Dir.pwd}"
92+
raise RuntimeError.new if raise_error
93+
end
94+
95+
result
96+
end
97+
98+
private
99+
100+
def free_file_no(directory)
101+
(1..).each do |file_no|
102+
out_path = File.join(directory, "output_%03d.csv" % file_no)
103+
return file_no unless File.exist?(out_path)
104+
end
105+
end
41106
end
42107
end

run_benchmarks.rb

Lines changed: 5 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
require_relative 'lib/cpu_config'
1212
require_relative 'lib/benchmark_runner'
1313
require_relative 'lib/benchmark_suite'
14-
require_relative 'lib/table_formatter'
1514
require_relative 'lib/argument_parser'
1615
require_relative 'lib/results_table_builder'
1716

@@ -57,65 +56,25 @@
5756
puts
5857

5958
# Build results table
60-
all_names = args.executables.keys
61-
base_name, *other_names = all_names
6259
builder = ResultsTableBuilder.new(
63-
executable_names: all_names,
60+
executable_names: ruby_descriptions.keys,
6461
bench_data: bench_data,
6562
include_rss: args.rss
6663
)
6764
table, format = builder.build
6865

69-
output_path = nil
70-
if args.out_override
71-
output_path = args.out_override
72-
else
73-
# If no out path is specified, find a free file index for the output files
74-
file_no = BenchmarkRunner.free_file_no(args.out_path)
75-
output_path = File.join(args.out_path, "output_%03d" % file_no)
76-
end
66+
output_path = BenchmarkRunner.output_path(args.out_path, out_override: args.out_override)
7767

7868
# Save the raw data as JSON
79-
out_json_path = output_path + ".json"
80-
File.open(out_json_path, "w") do |file|
81-
out_data = {
82-
metadata: ruby_descriptions,
83-
raw_data: bench_data,
84-
}
85-
json_str = JSON.generate(out_data)
86-
file.write json_str
87-
end
69+
out_json_path = BenchmarkRunner.write_json(output_path, ruby_descriptions, bench_data)
8870

8971
# Save data as CSV so we can produce tables/graphs in a spreasheet program
9072
# NOTE: we don't do any number formatting for the output file because
9173
# we don't want to lose any precision
92-
output_rows = []
93-
ruby_descriptions.each do |key, value|
94-
output_rows.append([key, value])
95-
end
96-
output_rows.append([])
97-
output_rows.concat(table)
98-
out_tbl_path = output_path + ".csv"
99-
CSV.open(out_tbl_path, "wb") do |csv|
100-
output_rows.each do |row|
101-
csv << row
102-
end
103-
end
74+
BenchmarkRunner.write_csv(output_path, ruby_descriptions, table)
10475

10576
# Save the output in a text file that we can easily refer to
106-
output_str = ""
107-
ruby_descriptions.each do |key, value|
108-
output_str << "#{key}: #{value}\n"
109-
end
110-
output_str += "\n"
111-
output_str += TableFormatter.new(table, format, bench_failures).to_s + "\n"
112-
unless other_names.empty?
113-
output_str << "Legend:\n"
114-
other_names.each do |name|
115-
output_str << "- #{name} 1st itr: ratio of #{base_name}/#{name} time for the first benchmarking iteration.\n"
116-
output_str << "- #{base_name}/#{name}: ratio of #{base_name}/#{name} time. Higher is better for #{name}. Above 1 represents a speedup.\n"
117-
end
118-
end
77+
output_str = BenchmarkRunner.build_output_text(ruby_descriptions, table, format, bench_failures)
11978
out_txt_path = output_path + ".txt"
12079
File.open(out_txt_path, "w") { |f| f.write output_str }
12180

0 commit comments

Comments
 (0)