@@ -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 ,
@@ -608,15 +650,44 @@ impl<'gctx> Timings<'gctx> {
608
650
let mut units: Vec < & UnitTime > = self . unit_times . iter ( ) . collect ( ) ;
609
651
units. sort_unstable_by ( |a, b| b. duration . partial_cmp ( & a. duration ) . unwrap ( ) ) ;
610
652
653
+ // Make the first "letter" uppercase. We could probably just assume ASCII here, but this
654
+ // should be Unicode compatible.
655
+ fn capitalize ( s : & str ) -> String {
656
+ let first_char = s
657
+ . chars ( )
658
+ . next ( )
659
+ . map ( |c| c. to_uppercase ( ) . to_string ( ) )
660
+ . unwrap_or_default ( ) ;
661
+ format ! ( "{first_char}{}" , s. chars( ) . skip( 1 ) . collect:: <String >( ) )
662
+ }
663
+
611
664
// We can have a bunch of situations here.
612
665
// - -Zsection-timings is enabled, and we received some custom sections, in which
613
666
// case we use them to determine the headers.
614
667
// - We have at least one rmeta time, so we hard-code Frontend and Codegen headers.
615
668
// - We only have total durations, so we don't add any additional headers.
616
- let aggregated: Vec < AggregatedSections > =
617
- units. iter ( ) . map ( |u| u. aggregate_sections ( ) ) . collect ( ) ;
669
+ let aggregated: Vec < AggregatedSections > = units
670
+ . iter ( )
671
+ . map ( |u|
672
+ // Normalize the section names so that they are capitalized, so that we can later
673
+ // refer to them with the capitalized name both when computing headers and when
674
+ // looking up cells.
675
+ match u. aggregate_sections ( ) {
676
+ AggregatedSections :: Sections ( sections) => AggregatedSections :: Sections (
677
+ sections. into_iter ( )
678
+ . map ( |( name, data) | ( capitalize ( & name) , data) )
679
+ . collect ( )
680
+ ) ,
681
+ s => s
682
+ } )
683
+ . collect ( ) ;
618
684
619
- let headers: Vec < String > = if aggregated
685
+ let headers: Vec < String > = if let Some ( sections) = aggregated. iter ( ) . find_map ( |s| match s {
686
+ AggregatedSections :: Sections ( sections) => Some ( sections) ,
687
+ _ => None ,
688
+ } ) {
689
+ sections. into_iter ( ) . map ( |s| s. 0 . clone ( ) ) . collect ( )
690
+ } else if aggregated
620
691
. iter ( )
621
692
. any ( |s| matches ! ( s, AggregatedSections :: OnlyMetadataTime { .. } ) )
622
693
{
@@ -663,6 +734,11 @@ impl<'gctx> Timings<'gctx> {
663
734
let mut cells: HashMap < & str , SectionData > = Default :: default ( ) ;
664
735
665
736
match & aggregated_sections {
737
+ AggregatedSections :: Sections ( sections) => {
738
+ for ( name, data) in sections {
739
+ cells. insert ( & name, * data) ;
740
+ }
741
+ }
666
742
AggregatedSections :: OnlyMetadataTime { frontend, codegen } => {
667
743
cells. insert ( FRONTEND_SECTION_NAME , * frontend) ;
668
744
cells. insert ( CODEGEN_SECTION_NAME , * codegen) ;
0 commit comments