Skip to content

Commit 71ab210

Browse files
committed
Show --zjit-stats in the summary table
When --zjit-stats=stat1,stat2 is passed, add those stats as columns in the summary table in addition to printing per-iteration diffs. This generalizes the approach so any ZJIT stat can be surfaced in the summary without needing a dedicated flag per stat.
1 parent 0b72888 commit 71ab210

File tree

3 files changed

+32
-7
lines changed

3 files changed

+32
-7
lines changed

lib/argument_parser.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class ArgumentParser
2525
:with_pre_init,
2626
:pvalue,
2727
:interleave,
28+
:zjit_stats,
2829
keyword_init: true
2930
)
3031

@@ -125,8 +126,9 @@ def parse(argv)
125126
ENV["YJIT_BENCH_STATS"] = str
126127
end
127128

128-
opts.on("--zjit-stats=STATS", "print ZJIT stats at each iteration for the default harness") do |str|
129+
opts.on("--zjit-stats=STATS", "print ZJIT stats at each iteration and show them in the summary table") do |str|
129130
ENV["ZJIT_BENCH_STATS"] = str
131+
args.zjit_stats = str.split(",")
130132
end
131133

132134
opts.on("--yjit_opts=OPT_STRING", "string of command-line options to run YJIT with (ignored if you use -e)") do |str|
@@ -236,6 +238,7 @@ def default_args
236238
rss: false,
237239
pvalue: false,
238240
interleave: false,
241+
zjit_stats: [],
239242
graph: false,
240243
no_pinning: false,
241244
force_pinning: false,

lib/benchmark_runner/cli.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ def run
9494
executable_names: ruby_descriptions.keys,
9595
bench_data: bench_data,
9696
include_rss: args.rss,
97-
include_pvalue: args.pvalue
97+
include_pvalue: args.pvalue,
98+
zjit_stats: args.zjit_stats
9899
)
99100
table, format = builder.build
100101

lib/results_table_builder.rb

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ class ResultsTableBuilder
55
SECONDS_TO_MS = 1000.0
66
BYTES_TO_MIB = 1024.0 * 1024.0
77

8-
def initialize(executable_names:, bench_data:, include_rss: false, include_pvalue: false)
8+
def initialize(executable_names:, bench_data:, include_rss: false, include_pvalue: false, zjit_stats: [])
99
@executable_names = executable_names
1010
@bench_data = bench_data
1111
@include_rss = include_rss
1212
@include_pvalue = include_pvalue
13+
@zjit_stats = zjit_stats
1314
@include_gc = detect_gc_data(bench_data)
1415
@base_name = executable_names.first
1516
@other_names = executable_names[1..]
@@ -46,6 +47,7 @@ def build_header
4647
@executable_names.each do |name|
4748
header << "#{name} (ms)"
4849
header << "RSS (MiB)" if @include_rss
50+
@zjit_stats.each { |stat| header << stat }
4951
if @include_gc
5052
header << "#{name} mark (ms)"
5153
header << "#{name} sweep (ms)"
@@ -85,6 +87,7 @@ def build_format
8587
@executable_names.each do |_name|
8688
format << "%s"
8789
format << "%.1f" if @include_rss
90+
@zjit_stats.each { format << "%s" }
8891
if @include_gc
8992
format << "%s"
9093
format << "%s"
@@ -127,6 +130,11 @@ def build_row(bench_name)
127130
base_t, *other_ts = times_no_warmup
128131
base_rss, *other_rsss = rsss
129132

133+
# Extract zjit stats: { stat_name => [base_val, other1_val, ...] }
134+
zjit_stat_values = @zjit_stats.map do |stat|
135+
[stat, extract_zjit_stat(bench_name, stat)]
136+
end
137+
130138
if @include_gc
131139
marking_times = extract_gc_times(bench_name, 'gc_marking_time_bench')
132140
sweeping_times = extract_gc_times(bench_name, 'gc_sweeping_time_bench')
@@ -135,35 +143,42 @@ def build_row(bench_name)
135143
end
136144

137145
row = [bench_name]
138-
build_base_columns(row, base_t, base_rss, base_mark, base_sweep)
139-
build_comparison_columns(row, other_ts, other_rsss, other_marks, other_sweeps)
146+
build_base_columns(row, base_t, base_rss, zjit_stat_values, 0, base_mark, base_sweep)
147+
build_comparison_columns(row, other_ts, other_rsss, zjit_stat_values, other_marks, other_sweeps)
140148
build_ratio_columns(row, base_t0, other_t0s, base_t, other_ts)
141149
build_rss_ratio_columns(row, base_rss, other_rsss)
142150
build_gc_ratio_columns(row, base_mark, other_marks, base_sweep, other_sweeps)
143151

144152
row
145153
end
146154

147-
def build_base_columns(row, base_t, base_rss, base_mark, base_sweep)
155+
def build_base_columns(row, base_t, base_rss, zjit_stat_values, exe_index, base_mark, base_sweep)
148156
row << format_time_with_stddev(base_t)
149157
row << base_rss if @include_rss
158+
zjit_stat_values.each { |_stat, values| row << format_stat(values[exe_index]) }
150159
if @include_gc
151160
row << format_time_with_stddev(base_mark)
152161
row << format_time_with_stddev(base_sweep)
153162
end
154163
end
155164

156-
def build_comparison_columns(row, other_ts, other_rsss, other_marks, other_sweeps)
165+
def build_comparison_columns(row, other_ts, other_rsss, zjit_stat_values, other_marks, other_sweeps)
157166
other_ts.each_with_index do |other_t, i|
158167
row << format_time_with_stddev(other_t)
159168
row << other_rsss[i] if @include_rss
169+
zjit_stat_values.each { |_stat, values| row << format_stat(values[i + 1]) }
160170
if @include_gc
161171
row << format_time_with_stddev(other_marks[i])
162172
row << format_time_with_stddev(other_sweeps[i])
163173
end
164174
end
165175
end
166176

177+
def format_stat(value)
178+
return "N/A" if value.nil?
179+
value.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, '\1,')
180+
end
181+
167182
def format_time_with_stddev(values)
168183
return "N/A" if values.nil? || values.empty?
169184
"%.1f ± %.1f%%" % [mean(values), stddev_percent(values)]
@@ -274,6 +289,12 @@ def extract_rss_values(bench_name)
274289
end
275290
end
276291

292+
def extract_zjit_stat(bench_name, key)
293+
@executable_names.map do |name|
294+
bench_data_for(name, bench_name).dig('zjit_stats', key)
295+
end
296+
end
297+
277298
def extract_gc_times(bench_name, key)
278299
@executable_names.map do |name|
279300
bench_data_for(name, bench_name)[key] || []

0 commit comments

Comments
 (0)