@@ -29,118 +29,121 @@ def bench(targets = None):
2929 cons .print ()
3030 cons .print (f"[bold]Benchmarking { format_list_to_string (ARG ('targets' ), 'magenta' )} ([magenta]{ os .path .relpath (bench_dirpath )} [/magenta]):[/bold]" )
3131 cons .indent ()
32- cons .print ()
3332
34- CASES = [ BenchCase (** case ) for case in file_load_yaml (MFC_BENCH_FILEPATH ) ]
33+ try :
34+ cons .print ()
3535
36- for case in CASES :
37- case .args = case .args + ARG ("--" )
38- case .path = os .path .abspath (case .path )
36+ CASES = [ BenchCase (** case ) for case in file_load_yaml (MFC_BENCH_FILEPATH ) ]
3937
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 } " )
38+ for case in CASES :
39+ case . args = case .args + ARG ( "--" )
40+ case . path = os . path . abspath ( case .path )
4341
44- results = {
45- "metadata" : {
46- "invocation" : sys .argv [1 :],
47- "lock" : dataclasses .asdict (CFG ())
48- },
49- "cases" : {},
50- }
42+ # Validate case file exists early
43+ if not os .path .exists (case .path ):
44+ raise MFCException (f"Benchmark case file not found: { case .path } " )
5145
52- failed_cases = []
46+ results = {
47+ "metadata" : {
48+ "invocation" : sys .argv [1 :],
49+ "lock" : dataclasses .asdict (CFG ())
50+ },
51+ "cases" : {},
52+ }
5353
54- for i , case in enumerate (CASES ):
55- summary_filepath = os .path .join (bench_dirpath , f"{ case .slug } .yaml" )
56- log_filepath = os .path .join (bench_dirpath , f"{ case .slug } .out" )
54+ failed_cases = []
5755
58- cons .print (f"{ str (i + 1 ).zfill (len (CASES ) // 10 + 1 )} /{ len (CASES )} : { case .slug } @ [bold]{ os .path .relpath (case .path )} [/bold]" )
59- cons .indent ()
60- cons .print ()
61- cons .print (f"> Log: [bold]{ os .path .relpath (log_filepath )} [/bold]" )
62- cons .print (f"> Summary: [bold]{ os .path .relpath (summary_filepath )} [/bold]" )
63-
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" , str (ARG ('mem' ))],
72- stdout = log_file ,
73- stderr = subprocess .STDOUT )
74-
75- # Check return code (handle CompletedProcess or int defensively)
76- rc = result .returncode if hasattr (result , "returncode" ) else result
77- if rc != 0 :
78- cons .print (f"[bold red]ERROR[/bold red]: Case { case .slug } failed with exit code { rc } " )
79- cons .print (f"[bold red] Check log at: { log_filepath } [/bold red]" )
80- failed_cases .append (case .slug )
81- continue
56+ for i , case in enumerate (CASES ):
57+ summary_filepath = os .path .join (bench_dirpath , f"{ case .slug } .yaml" )
58+ log_filepath = os .path .join (bench_dirpath , f"{ case .slug } .out" )
8259
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- continue
89-
90- # Load summary
91- summary = file_load_yaml (summary_filepath )
92-
93- # Validate all targets have required data
94- validation_failed = False
95- for target in targets :
96- if target .name not in summary :
97- cons .print (f"[bold red]ERROR[/bold red]: Target { target .name } missing from summary for { case .slug } " )
98- validation_failed = True
99- break
100-
101- if "exec" not in summary [target .name ]:
102- cons .print (f"[bold red]ERROR[/bold red]: 'exec' time missing for { target .name } in { case .slug } " )
103- validation_failed = True
104- break
105-
106- if target .name == "simulation" and "grind" not in summary [target .name ]:
107- cons .print (f"[bold red]ERROR[/bold red]: 'grind' time missing for simulation in { case .slug } " )
108- validation_failed = True
109- break
110-
111- if validation_failed :
60+ cons .print (f"{ str (i + 1 ).zfill (len (CASES ) // 10 + 1 )} /{ len (CASES )} : { case .slug } @ [bold]{ os .path .relpath (case .path )} [/bold]" )
61+ cons .indent ()
62+ cons .print ()
63+ cons .print (f"> Log: [bold]{ os .path .relpath (log_filepath )} [/bold]" )
64+ cons .print (f"> Summary: [bold]{ os .path .relpath (summary_filepath )} [/bold]" )
65+
66+ try :
67+ with open (log_filepath , "w" ) as log_file :
68+ result = system (
69+ ["./mfc.sh" , "run" , case .path , "--case-optimization" ] +
70+ ["--targets" ] + [t .name for t in targets ] +
71+ ["--output-summary" , summary_filepath ] +
72+ case .args +
73+ ["--" , "--gbpp" , str (ARG ('mem' ))],
74+ stdout = log_file ,
75+ stderr = subprocess .STDOUT )
76+
77+ # Check return code (handle CompletedProcess or int defensively)
78+ rc = result .returncode if hasattr (result , "returncode" ) else result
79+ if rc != 0 :
80+ cons .print (f"[bold red]ERROR[/bold red]: Case { case .slug } failed with exit code { rc } " )
81+ cons .print (f"[bold red] Check log at: { log_filepath } [/bold red]" )
82+ failed_cases .append (case .slug )
83+ continue
84+
85+ # Validate summary file exists
86+ if not os .path .exists (summary_filepath ):
87+ cons .print (f"[bold red]ERROR[/bold red]: Summary file not created for { case .slug } " )
88+ cons .print (f"[bold red] Expected: { summary_filepath } [/bold red]" )
89+ failed_cases .append (case .slug )
90+ continue
91+
92+ # Load summary
93+ summary = file_load_yaml (summary_filepath )
94+
95+ # Validate all targets have required data
96+ validation_failed = False
97+ for target in targets :
98+ if target .name not in summary :
99+ cons .print (f"[bold red]ERROR[/bold red]: Target { target .name } missing from summary for { case .slug } " )
100+ validation_failed = True
101+ break
102+
103+ if "exec" not in summary [target .name ]:
104+ cons .print (f"[bold red]ERROR[/bold red]: 'exec' time missing for { target .name } in { case .slug } " )
105+ validation_failed = True
106+ break
107+
108+ if target .name == "simulation" and "grind" not in summary [target .name ]:
109+ cons .print (f"[bold red]ERROR[/bold red]: 'grind' time missing for simulation in { case .slug } " )
110+ validation_failed = True
111+ break
112+
113+ if validation_failed :
114+ failed_cases .append (case .slug )
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+ cons .print (f"[dim]{ traceback .format_exc ()} [/dim]" )
112127 failed_cases .append (case .slug )
113- continue
114-
115- # Add to results
116- results ["cases" ][case .slug ] = {
117- "description" : dataclasses .asdict (case ),
118- "output_summary" : summary ,
119- }
120- cons .print (f"[bold green]✓[/bold green] Case { case .slug } completed successfully" )
121-
122- except Exception as e :
123- cons .print (f"[bold red]ERROR[/bold red]: Unexpected error running { case .slug } : { e } " )
124- cons .print (f"[dim]{ traceback .format_exc ()} [/dim]" )
125- failed_cases .append (case .slug )
126- finally :
127- cons .unindent ()
128-
129- # Report results
130- if failed_cases :
131- cons .print ()
132- cons .print (f"[bold red]Failed cases ({ len (failed_cases )} ):[/bold red]" )
133- for slug in failed_cases :
134- cons .print (f" - { slug } " )
135- cons .print ()
136- raise MFCException (f"Benchmarking failed: { len (failed_cases )} /{ len (CASES )} cases failed" )
128+ finally :
129+ cons .unindent ()
130+
131+ # Report results
132+ if failed_cases :
133+ cons .print ()
134+ cons .print (f"[bold red]Failed cases ({ len (failed_cases )} ):[/bold red]" )
135+ for slug in failed_cases :
136+ cons .print (f" - { slug } " )
137+ cons .print ()
138+ raise MFCException (f"Benchmarking failed: { len (failed_cases )} /{ len (CASES )} cases failed" )
137139
138- # Write output
139- file_dump_yaml (ARG ("output" ), results )
140+ # Write output
141+ file_dump_yaml (ARG ("output" ), results )
140142
141- cons .print (f"Wrote results to [bold magenta]{ os .path .relpath (ARG ('output' ))} [/bold magenta]." )
143+ cons .print (f"Wrote results to [bold magenta]{ os .path .relpath (ARG ('output' ))} [/bold magenta]." )
142144
143- cons .unindent ()
145+ finally :
146+ cons .unindent ()
144147
145148
146149# TODO: This function is too long and not nicely written at all. Someone should
0 commit comments