@@ -5,6 +5,7 @@ use clap::Parser;
55use collector:: category:: Category ;
66use database:: { ArtifactId , Commit } ;
77use log:: debug;
8+ use rayon:: iter:: { IndexedParallelIterator , IntoParallelRefIterator , ParallelIterator } ;
89use std:: collections:: HashMap ;
910use std:: fs;
1011use std:: fs:: File ;
@@ -134,6 +135,10 @@ impl BenchmarkErrors {
134135 self . 0 += 1 ;
135136 }
136137
138+ fn add ( & mut self , count : usize ) {
139+ self . 0 += count;
140+ }
141+
137142 fn fail_if_nonzero ( self ) -> anyhow:: Result < ( ) > {
138143 if self . 0 > 0 {
139144 anyhow:: bail!( "{} benchmarks failed" , self . 0 )
@@ -684,18 +689,30 @@ fn profile(
684689 if let Profiler :: SelfProfile = profiler {
685690 check_measureme_installed ( ) . unwrap ( ) ;
686691 }
687- for ( i, benchmark) in benchmarks. iter ( ) . enumerate ( ) {
688- eprintln ! ( "{}" , n_normal_benchmarks_remaining( benchmarks. len( ) - i) ) ;
689- let mut processor = ProfileProcessor :: new ( profiler, out_dir, id) ;
690- let result = benchmark. measure ( & mut processor, & profiles, & scenarios, compiler, Some ( 1 ) ) ;
691- if let Err ( ref s) = result {
692- errors. incr ( ) ;
693- eprintln ! (
694- "collector error: Failed to profile '{}' with {:?}, recorded: {:?}" ,
695- benchmark. name, profiler, s
696- ) ;
697- }
698- }
692+
693+ let error_count: usize = benchmarks
694+ . par_iter ( )
695+ . enumerate ( )
696+ . map ( |( i, benchmark) | {
697+ let benchmark_id = format ! ( "{} ({}/{})" , benchmark. name, i + 1 , benchmarks. len( ) ) ;
698+ eprintln ! ( "Executing benchmark {benchmark_id}" ) ;
699+ let mut processor = ProfileProcessor :: new ( profiler, out_dir, id) ;
700+ let result =
701+ benchmark. measure ( & mut processor, & profiles, & scenarios, compiler, Some ( 1 ) ) ;
702+ eprintln ! ( "Finished benchmark {benchmark_id}" ) ;
703+
704+ if let Err ( ref s) = result {
705+ eprintln ! (
706+ "collector error: Failed to profile '{}' with {:?}, recorded: {:?}" ,
707+ benchmark. name, profiler, s
708+ ) ;
709+ 1
710+ } else {
711+ 0
712+ }
713+ } )
714+ . sum ( ) ;
715+ errors. add ( error_count) ;
699716}
700717
701718fn main ( ) {
@@ -859,6 +876,11 @@ enum Commands {
859876 // toolchain name, and `PathBuf` doesn't work well for the latter.
860877 #[ clap( long) ]
861878 rustc2 : Option < String > ,
879+
880+ /// How many benchmarks should be profiled in parallel.
881+ /// This flag is only supported for certain profilers
882+ #[ clap( long, short = 'j' , default_value = "1" ) ]
883+ jobs : u64 ,
862884 } ,
863885
864886 /// Installs the next commit for perf.rust-lang.org
@@ -1089,7 +1111,16 @@ fn main_result() -> anyhow::Result<i32> {
10891111 local,
10901112 out_dir,
10911113 rustc2,
1114+ jobs,
10921115 } => {
1116+ let jobs = jobs. max ( 1 ) ;
1117+ if jobs > 1 && !profiler. supports_parallel_execution ( ) {
1118+ anyhow:: bail!(
1119+ "Profiler {:?} does not support parallel execution." ,
1120+ profiler
1121+ ) ;
1122+ }
1123+
10931124 let profiles = Profile :: expand_all ( & local. profiles ) ;
10941125 let scenarios = Scenario :: expand_all ( & local. scenarios ) ;
10951126
@@ -1102,6 +1133,12 @@ fn main_result() -> anyhow::Result<i32> {
11021133
11031134 let mut errors = BenchmarkErrors :: new ( ) ;
11041135
1136+ eprintln ! ( "Running with {jobs} job(s)" ) ;
1137+ rayon:: ThreadPoolBuilder :: new ( )
1138+ . num_threads ( jobs as usize )
1139+ . build_global ( )
1140+ . unwrap ( ) ;
1141+
11051142 let mut get_toolchain_and_profile =
11061143 |rustc : & str , suffix : & str | -> anyhow:: Result < String > {
11071144 let ( rustc, rustdoc, cargo, id) = get_local_toolchain (
0 commit comments