11use crate :: benchmark:: profile:: Profile ;
22use crate :: toolchain:: { get_local_toolchain, LocalToolchain } ;
33use benchlib:: benchmark:: passes_filter;
4- use benchlib:: messages:: BenchmarkResult ;
4+ use benchlib:: comm :: messages:: BenchmarkMessage ;
55use cargo_metadata:: Message ;
6+ use std:: io:: { BufRead , BufReader } ;
67use std:: path:: { Path , PathBuf } ;
7- use std:: process:: Command ;
8+ use std:: process:: { Command , Stdio } ;
89
910#[ derive( Debug ) ]
1011struct BenchmarkBinary {
1112 path : PathBuf ,
1213 benchmark_names : Vec < String > ,
1314}
1415
16+ impl BenchmarkBinary {
17+ fn name ( & self ) -> & str {
18+ self . path . file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( )
19+ }
20+ }
21+
1522#[ derive( Debug ) ]
1623struct BenchmarkDatabase {
1724 binaries : Vec < BenchmarkBinary > ,
@@ -73,25 +80,40 @@ pub fn bench_runtime(
7380 total_benchmark_count - filtered
7481 ) ;
7582
83+ let mut benchmark_index = 0 ;
7684 for binary in benchmark_db. binaries {
77- let name = binary. path . file_name ( ) . and_then ( |s| s. to_str ( ) ) . unwrap ( ) ;
78-
79- let data: Vec < BenchmarkResult > = execute_runtime_binary ( & binary. path , name, & filter) ?;
80- // TODO: do something with the result
81- println ! ( "{name}: {:?}" , data) ;
85+ for message in execute_runtime_benchmark ( & binary. path , & filter) ? {
86+ let message = message. map_err ( |err| {
87+ anyhow:: anyhow!(
88+ "Cannot parse BenchmarkMessage from benchmark {}: {err:?}" ,
89+ binary. path. display( )
90+ )
91+ } ) ?;
92+ match message {
93+ BenchmarkMessage :: Stats ( stats) => {
94+ benchmark_index += 1 ;
95+ println ! (
96+ "Finished {}/{} ({}/{})" ,
97+ binary. name( ) ,
98+ stats. name,
99+ benchmark_index,
100+ filtered
101+ ) ;
102+ }
103+ }
104+ }
82105 }
83106
84107 Ok ( ( ) )
85108}
86109
87- /// Execute a single runtime benchmark suite defined in a binary crate located in
110+ /// Starts executing a single runtime benchmark suite defined in a binary crate located in
88111/// `runtime-benchmarks`. The binary is expected to use benchlib's `BenchmarkSuite` to execute
89- /// a set of runtime benchmarks and return a list of `BenchmarkResult `s encoded as JSON.
90- fn execute_runtime_binary (
112+ /// a set of runtime benchmarks and print `BenchmarkMessage `s encoded as JSON, one per line .
113+ fn execute_runtime_benchmark (
91114 binary : & Path ,
92- name : & str ,
93115 filter : & BenchmarkFilter ,
94- ) -> anyhow:: Result < Vec < BenchmarkResult > > {
116+ ) -> anyhow:: Result < impl Iterator < Item = anyhow :: Result < BenchmarkMessage > > > {
95117 // Turn off ASLR
96118 let mut command = Command :: new ( "setarch" ) ;
97119 command. arg ( std:: env:: consts:: ARCH ) ;
@@ -106,19 +128,16 @@ fn execute_runtime_binary(
106128 command. args ( & [ "--include" , include] ) ;
107129 }
108130
109- let result = command. output ( ) ?;
110-
111- if !result. status . success ( ) {
112- return Err ( anyhow:: anyhow!(
113- "Failed to run runtime benchmark {name}\n {}\n {}" ,
114- String :: from_utf8_lossy( & result. stdout) ,
115- String :: from_utf8_lossy( & result. stderr)
116- ) ) ;
117- }
118-
119- log:: info!( "Successfully ran runtime benchmark {name}" ) ;
131+ command. stdout ( Stdio :: piped ( ) ) ;
132+ let mut child = command. spawn ( ) ?;
133+ let stdout = child. stdout . take ( ) . unwrap ( ) ;
120134
121- Ok ( serde_json:: from_slice ( & result. stdout ) ?)
135+ let reader = BufReader :: new ( stdout) ;
136+ let iterator = reader. lines ( ) . map ( |line| {
137+ line. and_then ( |line| Ok ( serde_json:: from_str :: < BenchmarkMessage > ( & line) ?) )
138+ . map_err ( |err| err. into ( ) )
139+ } ) ;
140+ Ok ( iterator)
122141}
123142
124143/// Compiles all runtime benchmarks and returns the stdout output of Cargo.
0 commit comments