@@ -16,6 +16,7 @@ class BenchCase:
1616 path : str
1717 args : typing .List [str ]
1818
19+ # pylint: disable=too-many-locals, too-many-branches, too-many-statements
1920def bench (targets = None ):
2021 if targets is None :
2122 targets = ARG ("targets" )
@@ -36,6 +37,10 @@ def bench(targets = None):
3637 case .args = case .args + ARG ("--" )
3738 case .path = os .path .abspath (case .path )
3839
40+ # Validate case file exists early
41+ if not os .path .exists (case .path ):
42+ raise MFCException (f"Benchmark case file not found: { case .path } " )
43+
3944 results = {
4045 "metadata" : {
4146 "invocation" : sys .argv [1 :],
@@ -44,6 +49,8 @@ def bench(targets = None):
4449 "cases" : {},
4550 }
4651
52+ failed_cases = []
53+
4754 for i , case in enumerate (CASES ):
4855 summary_filepath = os .path .join (bench_dirpath , f"{ case .slug } .yaml" )
4956 log_filepath = os .path .join (bench_dirpath , f"{ case .slug } .out" )
@@ -54,21 +61,82 @@ def bench(targets = None):
5461 cons .print (f"> Log: [bold]{ os .path .relpath (log_filepath )} [/bold]" )
5562 cons .print (f"> Summary: [bold]{ os .path .relpath (summary_filepath )} [/bold]" )
5663
57- with open (log_filepath , "w" ) as log_file :
58- system (
59- ["./mfc.sh" , "run" , case .path , "--case-optimization" ] +
60- ["--targets" ] + [t .name for t in targets ] +
61- ["--output-summary" , summary_filepath ] +
62- case .args +
63- ["--" , "--gbpp" , ARG ('mem' )],
64- stdout = log_file ,
65- stderr = subprocess .STDOUT )
66-
67- results ["cases" ][case .slug ] = {
68- "description" : dataclasses .asdict (case ),
69- "output_summary" : file_load_yaml (summary_filepath ),
70- }
64+ try :
65+ with open (log_filepath , "w" ) as log_file :
66+ result = system (
67+ ["./mfc.sh" , "run" , case .path , "--case-optimization" ] +
68+ ["--targets" ] + [t .name for t in targets ] +
69+ ["--output-summary" , summary_filepath ] +
70+ case .args +
71+ ["--" , "--gbpp" , ARG ('mem' )],
72+ stdout = log_file ,
73+ stderr = subprocess .STDOUT )
74+
75+ # Check return code
76+ if result .returncode != 0 :
77+ cons .print (f"[bold red]ERROR[/bold red]: Case { case .slug } failed with exit code { result .returncode } " )
78+ cons .print (f"[bold red] Check log at: { log_filepath } [/bold red]" )
79+ failed_cases .append (case .slug )
80+ cons .unindent ()
81+ continue
82+
83+ # Validate summary file exists
84+ if not os .path .exists (summary_filepath ):
85+ cons .print (f"[bold red]ERROR[/bold red]: Summary file not created for { case .slug } " )
86+ cons .print (f"[bold red] Expected: { summary_filepath } [/bold red]" )
87+ failed_cases .append (case .slug )
88+ cons .unindent ()
89+ continue
90+
91+ # Load summary
92+ summary = file_load_yaml (summary_filepath )
93+
94+ # Validate all targets have required data
95+ validation_failed = False
96+ for target in targets :
97+ if target .name not in summary :
98+ cons .print (f"[bold red]ERROR[/bold red]: Target { target .name } missing from summary for { case .slug } " )
99+ validation_failed = True
100+ break
101+
102+ if "exec" not in summary [target .name ]:
103+ cons .print (f"[bold red]ERROR[/bold red]: 'exec' time missing for { target .name } in { case .slug } " )
104+ validation_failed = True
105+ break
106+
107+ if target .name == "simulation" and "grind" not in summary [target .name ]:
108+ cons .print (f"[bold red]ERROR[/bold red]: 'grind' time missing for simulation in { case .slug } " )
109+ validation_failed = True
110+ break
111+
112+ if validation_failed :
113+ failed_cases .append (case .slug )
114+ cons .unindent ()
115+ continue
116+
117+ # Add to results
118+ results ["cases" ][case .slug ] = {
119+ "description" : dataclasses .asdict (case ),
120+ "output_summary" : summary ,
121+ }
122+ cons .print (f"[bold green]✓[/bold green] Case { case .slug } completed successfully" )
123+
124+ except Exception as e :
125+ cons .print (f"[bold red]ERROR[/bold red]: Unexpected error running { case .slug } : { e } " )
126+ failed_cases .append (case .slug )
127+
128+ cons .unindent ()
129+
130+ # Report results
131+ if failed_cases :
132+ cons .print ()
133+ cons .print (f"[bold red]Failed cases ({ len (failed_cases )} ):[/bold red]" )
134+ for slug in failed_cases :
135+ cons .print (f" - { slug } " )
136+ cons .print ()
137+ raise MFCException (f"Benchmarking failed: { len (failed_cases )} /{ len (CASES )} cases failed" )
71138
139+ # Write output
72140 file_dump_yaml (ARG ("output" ), results )
73141
74142 cons .print (f"Wrote results to [bold magenta]{ os .path .relpath (ARG ('output' ))} [/bold magenta]." )
@@ -140,8 +208,9 @@ def diff():
140208 if grind_time_value < 0.95 :
141209 cons .print (f"[bold red]Error[/bold red]: Benchmarking failed since grind time speedup for { target .name } below acceptable threshold (<0.95) - Case: { slug } " )
142210 err = 1
143- except Exception as _ :
144- pass
211+ except Exception as e :
212+ cons .print (f"[bold red]ERROR[/bold red]: Failed to compute speedup for { target .name } in { slug } : { e } " )
213+ err = 1
145214
146215 table .add_row (f"[magenta]{ slug } [/magenta]" , * speedups )
147216
0 commit comments