@@ -104,7 +104,47 @@ impl UnitTime {
104
104
fn aggregate_sections ( & self ) -> AggregatedSections {
105
105
let end = self . duration ;
106
106
107
- if let Some ( rmeta) = self . rmeta_time {
107
+ if !self . sections . is_empty ( ) {
108
+ // We have some detailed compilation section timings, so we postprocess them
109
+ // Since it is possible that we do not have an end timestamp for a given compilation
110
+ // section, we need to iterate them and if an end is missing, we assign the end of
111
+ // the section to the start of the following section.
112
+
113
+ let mut sections = vec ! [ ] ;
114
+
115
+ // The frontend section is currently implicit in rustc, it is assumed to start at
116
+ // compilation start and end when codegen starts. So we hard-code it here.
117
+ let mut previous_section = (
118
+ FRONTEND_SECTION_NAME . to_string ( ) ,
119
+ CompilationSection {
120
+ start : 0.0 ,
121
+ end : None ,
122
+ } ,
123
+ ) ;
124
+ for ( name, section) in self . sections . clone ( ) {
125
+ // Store the previous section, potentially setting its end to the start of the
126
+ // current section.
127
+ sections. push ( (
128
+ previous_section. 0 . clone ( ) ,
129
+ SectionData {
130
+ start : previous_section. 1 . start ,
131
+ end : previous_section. 1 . end . unwrap_or ( section. start ) ,
132
+ } ,
133
+ ) ) ;
134
+ previous_section = ( name, section) ;
135
+ }
136
+ // Store the last section, potentially setting its end to the end of the whole
137
+ // compilation.
138
+ sections. push ( (
139
+ previous_section. 0 . clone ( ) ,
140
+ SectionData {
141
+ start : previous_section. 1 . start ,
142
+ end : previous_section. 1 . end . unwrap_or ( end) ,
143
+ } ,
144
+ ) ) ;
145
+
146
+ AggregatedSections :: Sections ( sections)
147
+ } else if let Some ( rmeta) = self . rmeta_time {
108
148
// We only know when the rmeta time was generated
109
149
AggregatedSections :: OnlyMetadataTime {
110
150
frontend : SectionData {
@@ -152,6 +192,8 @@ impl SectionData {
152
192
/// Contains post-processed data of individual compilation sections.
153
193
#[ derive( serde:: Serialize ) ]
154
194
enum AggregatedSections {
195
+ /// We know the names and durations of individual compilation sections
196
+ Sections ( Vec < ( String , SectionData ) > ) ,
155
197
/// We only know when .rmeta was generated, so we can distill frontend and codegen time.
156
198
OnlyMetadataTime {
157
199
frontend : SectionData ,
@@ -609,15 +651,44 @@ impl<'gctx> Timings<'gctx> {
609
651
let mut units: Vec < & UnitTime > = self . unit_times . iter ( ) . collect ( ) ;
610
652
units. sort_unstable_by ( |a, b| b. duration . partial_cmp ( & a. duration ) . unwrap ( ) ) ;
611
653
654
+ // Make the first "letter" uppercase. We could probably just assume ASCII here, but this
655
+ // should be Unicode compatible.
656
+ fn capitalize ( s : & str ) -> String {
657
+ let first_char = s
658
+ . chars ( )
659
+ . next ( )
660
+ . map ( |c| c. to_uppercase ( ) . to_string ( ) )
661
+ . unwrap_or_default ( ) ;
662
+ format ! ( "{first_char}{}" , s. chars( ) . skip( 1 ) . collect:: <String >( ) )
663
+ }
664
+
612
665
// We can have a bunch of situations here.
613
666
// - -Zsection-timings is enabled, and we received some custom sections, in which
614
667
// case we use them to determine the headers.
615
668
// - We have at least one rmeta time, so we hard-code Frontend and Codegen headers.
616
669
// - We only have total durations, so we don't add any additional headers.
617
- let aggregated: Vec < AggregatedSections > =
618
- units. iter ( ) . map ( |u| u. aggregate_sections ( ) ) . collect ( ) ;
670
+ let aggregated: Vec < AggregatedSections > = units
671
+ . iter ( )
672
+ . map ( |u|
673
+ // Normalize the section names so that they are capitalized, so that we can later
674
+ // refer to them with the capitalized name both when computing headers and when
675
+ // looking up cells.
676
+ match u. aggregate_sections ( ) {
677
+ AggregatedSections :: Sections ( sections) => AggregatedSections :: Sections (
678
+ sections. into_iter ( )
679
+ . map ( |( name, data) | ( capitalize ( & name) , data) )
680
+ . collect ( )
681
+ ) ,
682
+ s => s
683
+ } )
684
+ . collect ( ) ;
619
685
620
- let headers: Vec < String > = if aggregated
686
+ let headers: Vec < String > = if let Some ( sections) = aggregated. iter ( ) . find_map ( |s| match s {
687
+ AggregatedSections :: Sections ( sections) => Some ( sections) ,
688
+ _ => None ,
689
+ } ) {
690
+ sections. into_iter ( ) . map ( |s| s. 0 . clone ( ) ) . collect ( )
691
+ } else if aggregated
621
692
. iter ( )
622
693
. any ( |s| matches ! ( s, AggregatedSections :: OnlyMetadataTime { .. } ) )
623
694
{
@@ -664,6 +735,11 @@ impl<'gctx> Timings<'gctx> {
664
735
let mut cells: HashMap < & str , SectionData > = Default :: default ( ) ;
665
736
666
737
match & aggregated_sections {
738
+ AggregatedSections :: Sections ( sections) => {
739
+ for ( name, data) in sections {
740
+ cells. insert ( & name, * data) ;
741
+ }
742
+ }
667
743
AggregatedSections :: OnlyMetadataTime { frontend, codegen } => {
668
744
cells. insert ( FRONTEND_SECTION_NAME , * frontend) ;
669
745
cells. insert ( CODEGEN_SECTION_NAME , * codegen) ;
0 commit comments