@@ -105,7 +105,47 @@ impl UnitTime {
105
105
fn aggregate_sections ( & self ) -> AggregatedSections {
106
106
let end = self . duration ;
107
107
108
- if let Some ( rmeta) = self . rmeta_time {
108
+ if !self . sections . is_empty ( ) {
109
+ // We have some detailed compilation section timings, so we postprocess them
110
+ // Since it is possible that we do not have an end timestamp for a given compilation
111
+ // section, we need to iterate them and if an end is missing, we assign the end of
112
+ // the section to the start of the following section.
113
+
114
+ let mut sections = vec ! [ ] ;
115
+
116
+ // The frontend section is currently implicit in rustc, it is assumed to start at
117
+ // compilation start and end when codegen starts. So we hard-code it here.
118
+ let mut previous_section = (
119
+ FRONTEND_SECTION_NAME . to_string ( ) ,
120
+ CompilationSection {
121
+ start : 0.0 ,
122
+ end : None ,
123
+ } ,
124
+ ) ;
125
+ for ( name, section) in self . sections . clone ( ) {
126
+ // Store the previous section, potentially setting its end to the start of the
127
+ // current section.
128
+ sections. push ( (
129
+ previous_section. 0 . clone ( ) ,
130
+ SectionData {
131
+ start : previous_section. 1 . start ,
132
+ end : previous_section. 1 . end . unwrap_or ( section. start ) ,
133
+ } ,
134
+ ) ) ;
135
+ previous_section = ( name, section) ;
136
+ }
137
+ // Store the last section, potentially setting its end to the end of the whole
138
+ // compilation.
139
+ sections. push ( (
140
+ previous_section. 0 . clone ( ) ,
141
+ SectionData {
142
+ start : previous_section. 1 . start ,
143
+ end : previous_section. 1 . end . unwrap_or ( end) ,
144
+ } ,
145
+ ) ) ;
146
+
147
+ AggregatedSections :: Sections ( sections)
148
+ } else if let Some ( rmeta) = self . rmeta_time {
109
149
// We only know when the rmeta time was generated
110
150
AggregatedSections :: OnlyMetadataTime {
111
151
frontend : SectionData {
@@ -153,6 +193,8 @@ impl SectionData {
153
193
/// Contains post-processed data of individual compilation sections.
154
194
#[ derive( serde:: Serialize ) ]
155
195
enum AggregatedSections {
196
+ /// We know the names and durations of individual compilation sections
197
+ Sections ( Vec < ( String , SectionData ) > ) ,
156
198
/// We only know when .rmeta was generated, so we can distill frontend and codegen time.
157
199
OnlyMetadataTime {
158
200
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