66require_relative '../benchmark_runner'
77require_relative '../benchmark_suite'
88require_relative '../results_table_builder'
9+ require_relative '../ractor_breakdown'
10+ require_relative '../row_layout'
911
1012module BenchmarkRunner
1113 class CLI
@@ -63,6 +65,9 @@ def run
6365 bench_start_time = Time . now . to_f
6466 bench_data = { }
6567 bench_failures = { }
68+ bench_harnesses = suite . benchmarks . each_with_object ( { } ) do |entry , h |
69+ h [ entry . name ] = suite . harness_for ( entry . name )
70+ end
6671
6772 if args . interleave
6873 args . executables . each_key { |name | bench_data [ name ] = { } }
@@ -104,7 +109,7 @@ def run
104109
105110 puts
106111
107- # Build results table
112+ # Build the results table
108113 builder = ResultsTableBuilder . new (
109114 executable_names : ruby_descriptions . keys ,
110115 bench_data : bench_data ,
@@ -125,7 +130,8 @@ def run
125130 BenchmarkRunner . write_csv ( output_path , ruby_descriptions , table )
126131
127132 # Save the output in a text file that we can easily refer to
128- output_str = BenchmarkRunner . build_output_text ( ruby_descriptions , table , format , bench_failures , include_rss : args . rss , include_gc : builder . include_gc? , include_pvalue : args . pvalue , gc_table : gc_table , gc_format : gc_format )
133+ output_sections = build_output_sections ( ruby_descriptions . keys , bench_data , bench_harnesses , bench_failures )
134+ output_str = BenchmarkRunner . build_output_text ( ruby_descriptions , table , format , bench_failures , include_rss : args . rss , include_gc : builder . include_gc? , include_pvalue : args . pvalue , gc_table : gc_table , gc_format : gc_format , sections : output_sections )
129135 out_txt_path = output_path + ".txt"
130136 File . open ( out_txt_path , "w" ) { |f | f . write output_str }
131137
@@ -149,5 +155,81 @@ def run
149155 exit ( 1 )
150156 end
151157 end
158+
159+ private
160+
161+ def build_output_sections ( executable_names , bench_data , bench_harnesses , bench_failures )
162+ ordered_names = sorted_benchmark_names ( executable_names , bench_data )
163+ failed_names = bench_failures . values . flat_map ( &:keys ) . uniq
164+ ordered_names . concat ( failed_names . reject { |name | ordered_names . include? ( name ) } )
165+
166+ names_by_harness = { }
167+ ordered_names . each do |bench_name |
168+ harness = bench_harnesses . fetch ( bench_name , args . harness )
169+ names_by_harness [ harness ] ||= [ ]
170+ names_by_harness [ harness ] << bench_name
171+ end
172+
173+ show_titles = names_by_harness . size > 1
174+ names_by_harness . map do |harness , names |
175+ section = build_output_section ( executable_names , bench_data , bench_failures , harness , names )
176+ section [ :title ] = nil unless show_titles
177+ section
178+ end
179+ end
180+
181+ def build_output_section ( executable_names , bench_data , bench_failures , harness , bench_names )
182+ section_data = slice_bench_data ( bench_data , bench_names )
183+ breakdown = RactorBreakdown . expand ( section_data )
184+ use_ractor_layout = harness == BenchmarkSuite ::RACTOR_HARNESS && !breakdown . groups . empty?
185+ layout = use_ractor_layout ? RactorRowLayout . new ( groups : breakdown . groups ) : FlatRowLayout . new
186+ display_data = use_ractor_layout ? breakdown . bench_data : section_data
187+
188+ builder = ResultsTableBuilder . new (
189+ executable_names : executable_names ,
190+ bench_data : display_data ,
191+ include_rss : args . rss ,
192+ include_pvalue : args . pvalue ,
193+ zjit_stats : args . zjit_stats ,
194+ row_layout : layout
195+ )
196+ table , format , gc_table , gc_format = builder . build
197+
198+ {
199+ title : harness ,
200+ table : table ,
201+ format : format ,
202+ failures : slice_failures ( bench_failures , bench_names ) ,
203+ include_gc : builder . include_gc? ,
204+ gc_table : gc_table ,
205+ gc_format : gc_format ,
206+ }
207+ end
208+
209+ def sorted_benchmark_names ( executable_names , bench_data )
210+ builder = ResultsTableBuilder . new (
211+ executable_names : executable_names ,
212+ bench_data : bench_data ,
213+ include_rss : args . rss ,
214+ include_pvalue : args . pvalue ,
215+ zjit_stats : args . zjit_stats
216+ )
217+ builder . bench_names
218+ end
219+
220+ def slice_bench_data ( bench_data , bench_names )
221+ wanted = bench_names . each_with_object ( { } ) { |name , h | h [ name ] = true }
222+ bench_data . each_with_object ( { } ) do |( executable , benchmarks ) , sliced |
223+ sliced [ executable ] = benchmarks . select { |name , _data | wanted [ name ] }
224+ end
225+ end
226+
227+ def slice_failures ( bench_failures , bench_names )
228+ wanted = bench_names . each_with_object ( { } ) { |name , h | h [ name ] = true }
229+ bench_failures . each_with_object ( { } ) do |( executable , failures ) , sliced |
230+ selected = failures . select { |name , _failure | wanted [ name ] }
231+ sliced [ executable ] = selected unless selected . empty?
232+ end
233+ end
152234 end
153235end
0 commit comments