1- use std:: io:: { BufRead , BufReader } ;
1+ use std:: io:: { BufRead , BufReader , Cursor } ;
22use std:: path:: Path ;
33use std:: process:: { Command , Stdio } ;
44
5+ use anyhow:: Context ;
56use thousands:: Separable ;
67
78use benchlib:: comm:: messages:: { BenchmarkMessage , BenchmarkResult , BenchmarkStats } ;
@@ -12,7 +13,7 @@ pub use benchmark::{
1213use database:: { ArtifactIdNumber , CollectionId , Connection } ;
1314
1415use crate :: utils:: git:: get_rustc_perf_commit;
15- use crate :: CollectorCtx ;
16+ use crate :: { run_command_with_output , CollectorCtx } ;
1617
1718mod benchmark;
1819
@@ -38,41 +39,62 @@ pub async fn bench_runtime(
3839 ) ;
3940
4041 let rustc_perf_version = get_rustc_perf_commit ( ) ;
41-
4242 let mut benchmark_index = 0 ;
4343 for group in suite. groups {
44- if ! collector. start_runtime_step ( conn, & group) . await {
44+ let Some ( step_name ) = collector. start_runtime_step ( conn, & group) . await else {
4545 eprintln ! ( "skipping {} -- already benchmarked" , group. name) ;
4646 continue ;
47- }
47+ } ;
4848
4949 let mut tx = conn. transaction ( ) . await ;
50- for message in execute_runtime_benchmark_binary ( & group. binary , & filter, iterations) ? {
51- let message = message. map_err ( |err| {
52- anyhow:: anyhow!(
53- "Cannot parse BenchmarkMessage from benchmark {}: {err:?}" ,
54- group. binary. display( )
55- )
56- } ) ?;
57- match message {
58- BenchmarkMessage :: Result ( result) => {
59- benchmark_index += 1 ;
60- println ! (
61- "Finished {}/{} ({}/{})" ,
62- group. name, result. name, benchmark_index, filtered
63- ) ;
64-
65- print_stats ( & result) ;
66- record_stats (
67- tx. conn ( ) ,
68- collector. artifact_row_id ,
69- & rustc_perf_version,
70- result,
50+
51+ // Async block is used to easily capture all results, it basically simulates a `try` block.
52+ // Extracting this into a separate function would be annoying, as there would be many
53+ // parameters.
54+ let result = async {
55+ let messages = execute_runtime_benchmark_binary ( & group. binary , & filter, iterations) ?;
56+ for message in messages {
57+ let message = message. map_err ( |err| {
58+ anyhow:: anyhow!(
59+ "Cannot parse BenchmarkMessage from benchmark {}: {err:?}" ,
60+ group. binary. display( )
7161 )
72- . await ;
62+ } ) ?;
63+ match message {
64+ BenchmarkMessage :: Result ( result) => {
65+ benchmark_index += 1 ;
66+ println ! (
67+ "Finished {}/{} ({}/{})" ,
68+ group. name, result. name, benchmark_index, filtered
69+ ) ;
70+
71+ print_stats ( & result) ;
72+ record_stats (
73+ tx. conn ( ) ,
74+ collector. artifact_row_id ,
75+ & rustc_perf_version,
76+ result,
77+ )
78+ . await ;
79+ }
7380 }
7481 }
82+
83+ Ok :: < _ , anyhow:: Error > ( ( ) )
7584 }
85+ . await
86+ . with_context ( || format ! ( "Failed to execute runtime benchmark group {}" , group. name) ) ;
87+
88+ if let Err ( error) = result {
89+ eprintln ! ( "collector error: {:#}" , error) ;
90+ tx. conn ( )
91+ . record_error (
92+ collector. artifact_row_id ,
93+ & step_name,
94+ & format ! ( "{:?}" , error) ,
95+ )
96+ . await ;
97+ } ;
7698
7799 collector. end_runtime_step ( tx. conn ( ) , & group) . await ;
78100 tx. commit ( )
@@ -178,6 +200,9 @@ fn execute_runtime_benchmark_binary(
178200 command. arg ( "--iterations" ) ;
179201 command. arg ( & iterations. to_string ( ) ) ;
180202
203+ // We want to see a backtrace if the benchmark panics
204+ command. env ( "RUST_BACKTRACE" , "1" ) ;
205+
181206 if let Some ( ref exclude) = filter. exclude {
182207 command. args ( [ "--exclude" , exclude] ) ;
183208 }
@@ -186,14 +211,21 @@ fn execute_runtime_benchmark_binary(
186211 }
187212
188213 command. stdout ( Stdio :: piped ( ) ) ;
189- let mut child = command. spawn ( ) ?;
190- let stdout = child. stdout . take ( ) . unwrap ( ) ;
214+ command. stderr ( Stdio :: piped ( ) ) ;
191215
192- let reader = BufReader :: new ( stdout) ;
193- let iterator = reader. lines ( ) . map ( |line| {
216+ let output = run_command_with_output ( & mut command) ?;
217+ if !output. status . success ( ) {
218+ return Err ( anyhow:: anyhow!(
219+ "Process finished with exit code {}\n {}" ,
220+ output. status. code( ) . unwrap_or( -1 ) ,
221+ String :: from_utf8_lossy( & output. stderr)
222+ ) ) ;
223+ }
224+
225+ let reader = BufReader :: new ( Cursor :: new ( output. stdout ) ) ;
226+ Ok ( reader. lines ( ) . map ( |line| {
194227 Ok ( line. and_then ( |line| Ok ( serde_json:: from_str :: < BenchmarkMessage > ( & line) ?) ) ?)
195- } ) ;
196- Ok ( iterator)
228+ } ) )
197229}
198230
199231fn calculate_mean < I : Iterator < Item = f64 > + Clone > ( iter : I ) -> f64 {
0 commit comments