@@ -23,7 +23,7 @@ use std::io::BufWriter;
23
23
use std:: io:: Write ;
24
24
use std:: path:: { Path , PathBuf } ;
25
25
use std:: process;
26
- use std:: process:: { Command , Stdio } ;
26
+ use std:: process:: Command ;
27
27
use std:: time:: Duration ;
28
28
use std:: { str, time:: Instant } ;
29
29
use tokio:: runtime:: Runtime ;
@@ -39,7 +39,8 @@ use collector::runtime::{profile_runtime, RuntimeCompilationOpts};
39
39
use collector:: toolchain:: {
40
40
create_toolchain_from_published_version, get_local_toolchain, Sysroot , Toolchain ,
41
41
} ;
42
- use collector:: utils:: wait_for_future;
42
+ use collector:: utils:: cachegrind:: cachegrind_diff;
43
+ use collector:: utils:: { is_installed, wait_for_future} ;
43
44
44
45
fn n_normal_benchmarks_remaining ( n : usize ) -> String {
45
46
let suffix = if n == 1 { "" } else { "s" } ;
@@ -123,10 +124,6 @@ fn check_installed(name: &str) -> anyhow::Result<()> {
123
124
Ok ( ( ) )
124
125
}
125
126
126
- fn is_installed ( name : & str ) -> bool {
127
- Command :: new ( name) . output ( ) . is_ok ( )
128
- }
129
-
130
127
fn generate_cachegrind_diffs (
131
128
id1 : & str ,
132
129
id2 : & str ,
@@ -161,27 +158,9 @@ fn generate_cachegrind_diffs(
161
158
let id_diff = format ! ( "{}-{}" , id1, id2) ;
162
159
let cgout1 = out_dir. join ( filename ( "cgout" , id1) ) ;
163
160
let cgout2 = out_dir. join ( filename ( "cgout" , id2) ) ;
164
- let cgfilt1 = out_dir. join ( filename ( "cgfilt" , id1) ) ;
165
- let cgfilt2 = out_dir. join ( filename ( "cgfilt" , id2) ) ;
166
- let cgfilt_diff = out_dir. join ( filename ( "cgfilt-diff" , & id_diff) ) ;
167
161
let cgann_diff = out_dir. join ( filename ( "cgann-diff" , & id_diff) ) ;
168
162
169
- if let Err ( e) = rustfilt ( & cgout1, & cgfilt1) {
170
- errors. incr ( ) ;
171
- eprintln ! ( "collector error: {:?}" , e) ;
172
- continue ;
173
- }
174
- if let Err ( e) = rustfilt ( & cgout2, & cgfilt2) {
175
- errors. incr ( ) ;
176
- eprintln ! ( "collector error: {:?}" , e) ;
177
- continue ;
178
- }
179
- if let Err ( e) = cg_diff ( & cgfilt1, & cgfilt2, & cgfilt_diff) {
180
- errors. incr ( ) ;
181
- eprintln ! ( "collector error: {:?}" , e) ;
182
- continue ;
183
- }
184
- if let Err ( e) = cg_annotate ( & cgfilt_diff, & cgann_diff) {
163
+ if let Err ( e) = cachegrind_diff ( & cgout1, & cgout2, & cgann_diff) {
185
164
errors. incr ( ) ;
186
165
eprintln ! ( "collector error: {:?}" , e) ;
187
166
continue ;
@@ -194,68 +173,6 @@ fn generate_cachegrind_diffs(
194
173
annotated_diffs
195
174
}
196
175
197
- /// Demangles symbols in a file using rustfilt and writes result to path.
198
- fn rustfilt ( cgout : & Path , path : & Path ) -> anyhow:: Result < ( ) > {
199
- if !is_installed ( "rustfilt" ) {
200
- anyhow:: bail!( "`rustfilt` not installed." ) ;
201
- }
202
- let output = Command :: new ( "rustfilt" )
203
- . arg ( "-i" )
204
- . arg ( cgout)
205
- . stderr ( Stdio :: inherit ( ) )
206
- . output ( )
207
- . context ( "failed to run `rustfilt`" ) ?;
208
-
209
- if !output. status . success ( ) {
210
- anyhow:: bail!( "failed to process output with rustfilt" ) ;
211
- }
212
-
213
- fs:: write ( path, output. stdout ) . context ( "failed to write `rustfilt` output" ) ?;
214
-
215
- Ok ( ( ) )
216
- }
217
-
218
- /// Compares two Cachegrind output files using cg_diff and writes result to path.
219
- fn cg_diff ( cgout1 : & Path , cgout2 : & Path , path : & Path ) -> anyhow:: Result < ( ) > {
220
- if !is_installed ( "cg_diff" ) {
221
- anyhow:: bail!( "`cg_diff` not installed." ) ;
222
- }
223
- let output = Command :: new ( "cg_diff" )
224
- . arg ( r"--mod-filename=s/\/rustc\/[^\/]*\///" )
225
- . arg ( "--mod-funcname=s/[.]llvm[.].*//" )
226
- . arg ( cgout1)
227
- . arg ( cgout2)
228
- . stderr ( Stdio :: inherit ( ) )
229
- . output ( )
230
- . context ( "failed to run `cg_diff`" ) ?;
231
-
232
- if !output. status . success ( ) {
233
- anyhow:: bail!( "failed to generate cachegrind diff" ) ;
234
- }
235
-
236
- fs:: write ( path, output. stdout ) . context ( "failed to write `cg_diff` output" ) ?;
237
-
238
- Ok ( ( ) )
239
- }
240
-
241
- /// Post process Cachegrind output file and writes resutl to path.
242
- fn cg_annotate ( cgout : & Path , path : & Path ) -> anyhow:: Result < ( ) > {
243
- let output = Command :: new ( "cg_annotate" )
244
- . arg ( "--show-percs=no" )
245
- . arg ( cgout)
246
- . stderr ( Stdio :: inherit ( ) )
247
- . output ( )
248
- . context ( "failed to run `cg_annotate`" ) ?;
249
-
250
- if !output. status . success ( ) {
251
- anyhow:: bail!( "failed to annotate cachegrind output" ) ;
252
- }
253
-
254
- fs:: write ( path, output. stdout ) . context ( "failed to write `cg_annotate` output" ) ?;
255
-
256
- Ok ( ( ) )
257
- }
258
-
259
176
#[ allow( clippy:: too_many_arguments) ]
260
177
fn profile_compile (
261
178
toolchain : & Toolchain ,
@@ -527,6 +444,10 @@ enum Commands {
527
444
/// The path to the local rustc used to compile the runtime benchmark
528
445
rustc : String ,
529
446
447
+ /// The path to a second local rustc used to compare with the baseline rustc
448
+ #[ arg( long) ]
449
+ rustc2 : Option < String > ,
450
+
530
451
/// Name of the benchmark that should be profiled
531
452
benchmark : String ,
532
453
} ,
@@ -716,21 +637,59 @@ fn main_result() -> anyhow::Result<i32> {
716
637
runtime,
717
638
profiler,
718
639
rustc,
640
+ rustc2,
719
641
benchmark,
720
642
} => {
721
- let toolchain =
722
- get_local_toolchain ( & [ Profile :: Opt ] , & rustc, None , None , None , "" , target_triple) ?;
723
- let suite = prepare_runtime_benchmark_suite (
724
- & toolchain,
725
- & runtime_benchmark_dir,
726
- CargoIsolationMode :: Cached ,
727
- runtime. group ,
728
- // Compile with debuginfo to have filenames and line numbers available in the
729
- // generated profiles.
730
- RuntimeCompilationOpts :: default ( ) . debug_info ( "1" ) ,
731
- ) ?
732
- . suite ;
733
- profile_runtime ( profiler, suite, & benchmark) ?;
643
+ let get_suite = |rustc : & str , id : & str | {
644
+ let toolchain = get_local_toolchain (
645
+ & [ Profile :: Opt ] ,
646
+ rustc,
647
+ None ,
648
+ None ,
649
+ None ,
650
+ id,
651
+ target_triple. clone ( ) ,
652
+ ) ?;
653
+ let suite = prepare_runtime_benchmark_suite (
654
+ & toolchain,
655
+ & runtime_benchmark_dir,
656
+ CargoIsolationMode :: Cached ,
657
+ runtime. group . clone ( ) ,
658
+ // Compile with debuginfo to have filenames and line numbers available in the
659
+ // generated profiles.
660
+ RuntimeCompilationOpts :: default ( ) . debug_info ( "1" ) ,
661
+ ) ?
662
+ . suite ;
663
+ Ok :: < _ , anyhow:: Error > ( ( toolchain, suite) )
664
+ } ;
665
+
666
+ println ! ( "Profiling {rustc}" ) ;
667
+ let ( toolchain1, suite1) = get_suite ( & rustc, "1" ) ?;
668
+ let profile1 = profile_runtime ( profiler. clone ( ) , & toolchain1, suite1, & benchmark) ?;
669
+
670
+ if let Some ( rustc2) = rustc2 {
671
+ match profiler {
672
+ RuntimeProfiler :: Cachegrind => {
673
+ println ! ( "Profiling {rustc2}" ) ;
674
+ let ( toolchain2, suite2) = get_suite ( & rustc2, "2" ) ?;
675
+ let profile2 = profile_runtime ( profiler, & toolchain2, suite2, & benchmark) ?;
676
+
677
+ let output = profile1. parent ( ) . unwrap ( ) . join ( format ! (
678
+ "cgann-diff-{}-{}-{benchmark}" ,
679
+ toolchain1. id, toolchain2. id
680
+ ) ) ;
681
+ cachegrind_diff ( & profile1, & profile2, & output)
682
+ . context ( "Cannot generate Cachegrind diff" ) ?;
683
+ println ! ( "Cachegrind diff stored in `{}`" , output. display( ) ) ;
684
+ }
685
+ }
686
+ } else {
687
+ println ! (
688
+ "Profiling complete, result can be found in `{}`" ,
689
+ profile1. display( )
690
+ ) ;
691
+ }
692
+
734
693
Ok ( 0 )
735
694
}
736
695
Commands :: BenchLocal {
@@ -971,7 +930,6 @@ fn main_result() -> anyhow::Result<i32> {
971
930
if profiler == Profiler :: Cachegrind {
972
931
check_installed ( "valgrind" ) ?;
973
932
check_installed ( "cg_annotate" ) ?;
974
- check_installed ( "rustfilt" ) ?;
975
933
976
934
let diffs = generate_cachegrind_diffs (
977
935
& id1,
0 commit comments