1
- use std:: io:: { BufRead , BufReader } ;
1
+ use std:: io:: { BufRead , BufReader , Cursor } ;
2
2
use std:: path:: Path ;
3
3
use std:: process:: { Command , Stdio } ;
4
4
5
+ use anyhow:: Context ;
5
6
use thousands:: Separable ;
6
7
7
8
use benchlib:: comm:: messages:: { BenchmarkMessage , BenchmarkResult , BenchmarkStats } ;
@@ -12,7 +13,7 @@ pub use benchmark::{
12
13
use database:: { ArtifactIdNumber , CollectionId , Connection } ;
13
14
14
15
use crate :: utils:: git:: get_rustc_perf_commit;
15
- use crate :: CollectorCtx ;
16
+ use crate :: { run_command_with_output , CollectorCtx } ;
16
17
17
18
mod benchmark;
18
19
@@ -38,41 +39,62 @@ pub async fn bench_runtime(
38
39
) ;
39
40
40
41
let rustc_perf_version = get_rustc_perf_commit ( ) ;
41
-
42
42
let mut benchmark_index = 0 ;
43
43
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 {
45
45
eprintln ! ( "skipping {} -- already benchmarked" , group. name) ;
46
46
continue ;
47
- }
47
+ } ;
48
48
49
49
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( )
71
61
)
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
+ }
73
80
}
74
81
}
82
+
83
+ Ok :: < _ , anyhow:: Error > ( ( ) )
75
84
}
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
+ } ;
76
98
77
99
collector. end_runtime_step ( tx. conn ( ) , & group) . await ;
78
100
tx. commit ( )
@@ -178,6 +200,9 @@ fn execute_runtime_benchmark_binary(
178
200
command. arg ( "--iterations" ) ;
179
201
command. arg ( & iterations. to_string ( ) ) ;
180
202
203
+ // We want to see a backtrace if the benchmark panics
204
+ command. env ( "RUST_BACKTRACE" , "1" ) ;
205
+
181
206
if let Some ( ref exclude) = filter. exclude {
182
207
command. args ( [ "--exclude" , exclude] ) ;
183
208
}
@@ -186,14 +211,21 @@ fn execute_runtime_benchmark_binary(
186
211
}
187
212
188
213
command. stdout ( Stdio :: piped ( ) ) ;
189
- let mut child = command. spawn ( ) ?;
190
- let stdout = child. stdout . take ( ) . unwrap ( ) ;
214
+ command. stderr ( Stdio :: piped ( ) ) ;
191
215
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| {
194
227
Ok ( line. and_then ( |line| Ok ( serde_json:: from_str :: < BenchmarkMessage > ( & line) ?) ) ?)
195
- } ) ;
196
- Ok ( iterator)
228
+ } ) )
197
229
}
198
230
199
231
fn calculate_mean < I : Iterator < Item = f64 > + Clone > ( iter : I ) -> f64 {
0 commit comments