@@ -74,6 +74,7 @@ pub struct Benchmark {
74
74
pub enum Profiler {
75
75
PerfStat ,
76
76
PerfStatSelfProfile ,
77
+ SelfProfile ,
77
78
TimePasses ,
78
79
PerfRecord ,
79
80
OProfile ,
@@ -99,6 +100,7 @@ impl Profiler {
99
100
// is rejected because it can't be used with the `profiler`
100
101
// subcommand. (It's used with `bench_local` instead.)
101
102
"perf-stat" => Err ( FromNameError :: PerfStat ) ,
103
+ "self-profile" => Ok ( Profiler :: SelfProfile ) ,
102
104
"time-passes" => Ok ( Profiler :: TimePasses ) ,
103
105
"perf-record" => Ok ( Profiler :: PerfRecord ) ,
104
106
"oprofile" => Ok ( Profiler :: OProfile ) ,
@@ -115,6 +117,7 @@ impl Profiler {
115
117
match self {
116
118
Profiler :: PerfStat => "perf-stat" ,
117
119
Profiler :: PerfStatSelfProfile => "perf-stat-self-profile" ,
120
+ Profiler :: SelfProfile => "self-profile" ,
118
121
Profiler :: TimePasses => "time-passes" ,
119
122
Profiler :: PerfRecord => "perf-record" ,
120
123
Profiler :: OProfile => "oprofile" ,
@@ -500,6 +503,66 @@ impl<'a> Processor for ProfileProcessor<'a> {
500
503
panic ! ( "unexpected profiler" ) ;
501
504
}
502
505
506
+ // -Zself-profile produces (via rustc-fake) a data directory called
507
+ // 'Zsp' containing three files with names of the form
508
+ // `$BENCHMARK-$PID.{events,string_data,string_index}`. We copy it
509
+ // from the temp dir to the output dir, renaming the files within
510
+ // as `Zsp.{events,string_data,string_index}` in the process, then
511
+ // post-process them with `summarize`, `flamegraph`, and `crox` to
512
+ // produce several data files in the output dir.
513
+ Profiler :: SelfProfile => {
514
+ let tmp_zsp_dir = filepath ( data. cwd . as_ref ( ) , "Zsp" ) ;
515
+ let zsp_dir = filepath ( self . output_dir , & out_file ( "Zsp" ) ) ;
516
+ let zsp_files_prefix = filepath ( & zsp_dir, "Zsp" ) ;
517
+ let summarize_file = filepath ( self . output_dir , & out_file ( "summarize" ) ) ;
518
+ let flamegraph_file = filepath ( self . output_dir , & out_file ( "flamegraph" ) ) ;
519
+ let crox_file = filepath ( self . output_dir , & out_file ( "crox" ) ) ;
520
+
521
+ // Move the directory.
522
+ if zsp_dir. exists ( ) {
523
+ fs:: remove_dir_all ( & zsp_dir) ?;
524
+ }
525
+ fs:: rename ( & tmp_zsp_dir, & zsp_dir) ?;
526
+
527
+ // Rename the data files.
528
+ for entry in fs:: read_dir ( & zsp_dir) . unwrap ( ) {
529
+ let filename = entry. unwrap ( ) . file_name ( ) ;
530
+ let filename_str = filename. to_str ( ) . unwrap ( ) ;
531
+ let path = filepath ( & zsp_dir, filename_str) ;
532
+ if filename_str. ends_with ( ".events" ) {
533
+ fs:: rename ( path, filepath ( & zsp_dir, "Zsp.events" ) ) ?;
534
+ } else if filename_str. ends_with ( ".string_data" ) {
535
+ fs:: rename ( path, filepath ( & zsp_dir, "Zsp.string_data" ) ) ?;
536
+ } else if filename_str. ends_with ( ".string_index" ) {
537
+ fs:: rename ( path, filepath ( & zsp_dir, "Zsp.string_index" ) ) ?;
538
+ } else {
539
+ panic ! ( "unexpected file {:?}" , path) ;
540
+ }
541
+ }
542
+
543
+ // Run `summarize`.
544
+ let mut summarize_cmd = Command :: new ( "summarize" ) ;
545
+ summarize_cmd
546
+ . arg ( "summarize" )
547
+ . arg ( & zsp_files_prefix) ;
548
+ let output = summarize_cmd. output ( ) ?;
549
+ fs:: write ( & summarize_file, & output. stdout ) ?;
550
+
551
+ // Run `flamegraph`.
552
+ let mut flamegraph_cmd = Command :: new ( "flamegraph" ) ;
553
+ flamegraph_cmd. arg ( & zsp_files_prefix) ;
554
+ flamegraph_cmd. status ( ) ?;
555
+ fs:: write ( & summarize_file, & output. stdout ) ?;
556
+ fs:: rename ( "rustc.svg" , flamegraph_file) ?;
557
+
558
+ // Run `crox`.
559
+ let mut crox_cmd = Command :: new ( "crox" ) ;
560
+ crox_cmd. arg ( & zsp_files_prefix) ;
561
+ crox_cmd. status ( ) ?;
562
+ fs:: write ( & summarize_file, & output. stdout ) ?;
563
+ fs:: rename ( "chrome_profiler.json" , crox_file) ?;
564
+ }
565
+
503
566
// -Ztime-passes writes its output to stdout. We copy that output
504
567
// into a file in the output dir.
505
568
Profiler :: TimePasses => {
@@ -528,7 +591,7 @@ impl<'a> Processor for ProfileProcessor<'a> {
528
591
let oprep_file = filepath ( self . output_dir , & out_file ( "oprep" ) ) ;
529
592
let opann_file = filepath ( self . output_dir , & out_file ( "opann" ) ) ;
530
593
531
- // Remove the directory if it exists .
594
+ // Move the directory.
532
595
if opout_dir. exists ( ) {
533
596
fs:: remove_dir_all ( & opout_dir) ?;
534
597
}
@@ -547,7 +610,6 @@ impl<'a> Processor for ProfileProcessor<'a> {
547
610
. arg ( "0.5" )
548
611
. arg ( & session_dir_arg) ;
549
612
let output = op_report_cmd. output ( ) ?;
550
-
551
613
fs:: write ( oprep_file, & output. stdout ) ?;
552
614
553
615
let mut op_annotate_cmd = Command :: new ( "opannotate" ) ;
@@ -558,7 +620,6 @@ impl<'a> Processor for ProfileProcessor<'a> {
558
620
. arg ( "0.5" )
559
621
. arg ( & session_dir_arg) ;
560
622
let output = op_annotate_cmd. output ( ) ?;
561
-
562
623
fs:: write ( opann_file, & output. stdout ) ?;
563
624
}
564
625
@@ -579,7 +640,6 @@ impl<'a> Processor for ProfileProcessor<'a> {
579
640
. arg ( "--show-percs=yes" )
580
641
. arg ( & cgout_file) ;
581
642
let output = cg_annotate_cmd. output ( ) ?;
582
-
583
643
fs:: write ( cgann_file, & output. stdout ) ?;
584
644
}
585
645
@@ -600,7 +660,6 @@ impl<'a> Processor for ProfileProcessor<'a> {
600
660
. arg ( "--show-percs=yes" )
601
661
. arg ( & clgout_file) ;
602
662
let output = clg_annotate_cmd. output ( ) ?;
603
-
604
663
fs:: write ( clgann_file, & output. stdout ) ?;
605
664
}
606
665
0 commit comments