@@ -5,6 +5,7 @@ use clap::Parser;
5
5
use collector:: category:: Category ;
6
6
use database:: { ArtifactId , Commit } ;
7
7
use log:: debug;
8
+ use rayon:: iter:: { IndexedParallelIterator , IntoParallelRefIterator , ParallelIterator } ;
8
9
use std:: collections:: HashMap ;
9
10
use std:: fs;
10
11
use std:: fs:: File ;
@@ -134,6 +135,10 @@ impl BenchmarkErrors {
134
135
self . 0 += 1 ;
135
136
}
136
137
138
+ fn add ( & mut self , count : usize ) {
139
+ self . 0 += count;
140
+ }
141
+
137
142
fn fail_if_nonzero ( self ) -> anyhow:: Result < ( ) > {
138
143
if self . 0 > 0 {
139
144
anyhow:: bail!( "{} benchmarks failed" , self . 0 )
@@ -684,18 +689,30 @@ fn profile(
684
689
if let Profiler :: SelfProfile = profiler {
685
690
check_measureme_installed ( ) . unwrap ( ) ;
686
691
}
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) ;
699
716
}
700
717
701
718
fn main ( ) {
@@ -859,6 +876,11 @@ enum Commands {
859
876
// toolchain name, and `PathBuf` doesn't work well for the latter.
860
877
#[ clap( long) ]
861
878
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 ,
862
884
} ,
863
885
864
886
/// Installs the next commit for perf.rust-lang.org
@@ -1089,7 +1111,16 @@ fn main_result() -> anyhow::Result<i32> {
1089
1111
local,
1090
1112
out_dir,
1091
1113
rustc2,
1114
+ jobs,
1092
1115
} => {
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
+
1093
1124
let profiles = Profile :: expand_all ( & local. profiles ) ;
1094
1125
let scenarios = Scenario :: expand_all ( & local. scenarios ) ;
1095
1126
@@ -1102,6 +1133,12 @@ fn main_result() -> anyhow::Result<i32> {
1102
1133
1103
1134
let mut errors = BenchmarkErrors :: new ( ) ;
1104
1135
1136
+ eprintln ! ( "Running with {jobs} job(s)" ) ;
1137
+ rayon:: ThreadPoolBuilder :: new ( )
1138
+ . num_threads ( jobs as usize )
1139
+ . build_global ( )
1140
+ . unwrap ( ) ;
1141
+
1105
1142
let mut get_toolchain_and_profile =
1106
1143
|rustc : & str , suffix : & str | -> anyhow:: Result < String > {
1107
1144
let ( rustc, rustdoc, cargo, id) = get_local_toolchain (
0 commit comments