@@ -105,7 +105,47 @@ impl UnitTime {
105105 fn aggregate_sections ( & self ) -> AggregatedSections {
106106 let end = self . duration ;
107107
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 {
109149 // We only know when the rmeta time was generated
110150 AggregatedSections :: OnlyMetadataTime {
111151 frontend : SectionData {
@@ -153,6 +193,8 @@ impl SectionData {
153193/// Contains post-processed data of individual compilation sections.
154194#[ derive( serde:: Serialize ) ]
155195enum AggregatedSections {
196+ /// We know the names and durations of individual compilation sections
197+ Sections ( Vec < ( String , SectionData ) > ) ,
156198 /// We only know when .rmeta was generated, so we can distill frontend and codegen time.
157199 OnlyMetadataTime {
158200 frontend : SectionData ,
@@ -609,15 +651,44 @@ impl<'gctx> Timings<'gctx> {
609651 let mut units: Vec < & UnitTime > = self . unit_times . iter ( ) . collect ( ) ;
610652 units. sort_unstable_by ( |a, b| b. duration . partial_cmp ( & a. duration ) . unwrap ( ) ) ;
611653
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+
612665 // We can have a bunch of situations here.
613666 // - -Zsection-timings is enabled, and we received some custom sections, in which
614667 // case we use them to determine the headers.
615668 // - We have at least one rmeta time, so we hard-code Frontend and Codegen headers.
616669 // - 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 ( ) ;
619685
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
621692 . iter ( )
622693 . any ( |s| matches ! ( s, AggregatedSections :: OnlyMetadataTime { .. } ) )
623694 {
@@ -664,6 +735,11 @@ impl<'gctx> Timings<'gctx> {
664735 let mut cells: HashMap < & str , SectionData > = Default :: default ( ) ;
665736
666737 match & aggregated_sections {
738+ AggregatedSections :: Sections ( sections) => {
739+ for ( name, data) in sections {
740+ cells. insert ( & name, * data) ;
741+ }
742+ }
667743 AggregatedSections :: OnlyMetadataTime { frontend, codegen } => {
668744 cells. insert ( FRONTEND_SECTION_NAME , * frontend) ;
669745 cells. insert ( CODEGEN_SECTION_NAME , * codegen) ;
0 commit comments