@@ -92,6 +92,50 @@ struct UnitTime {
92
92
sections : HashMap < String , TimingSection > ,
93
93
}
94
94
95
+ impl UnitTime {
96
+ fn aggregate_sections ( & self ) -> AggregatedSections {
97
+ let end = self . duration ;
98
+
99
+ let codegen_section = self . sections . get ( "codegen" ) ;
100
+ let link_section = self . sections . get ( "link" ) ;
101
+
102
+ // Best case: we know all three sections
103
+ if let ( Some ( codegen_section) , Some ( link_section) ) = ( codegen_section, link_section) {
104
+ let link_start = link_section. start ;
105
+ let codegen_end = codegen_section. end . unwrap_or ( link_start) ;
106
+
107
+ AggregatedSections :: Sections {
108
+ frontend : SectionData {
109
+ start : 0.0 ,
110
+ end : codegen_section. start ,
111
+ } ,
112
+ codegen : SectionData {
113
+ start : codegen_section. start ,
114
+ end : codegen_end,
115
+ } ,
116
+ linking : SectionData {
117
+ start : link_start,
118
+ end : link_section. end . unwrap_or ( end) ,
119
+ } ,
120
+ }
121
+ } else if let Some ( rmeta_time) = self . rmeta_time {
122
+ // We know at least the .rmeta time
123
+ AggregatedSections :: OnlyCodegenDuration {
124
+ frontend : SectionData {
125
+ start : 0.0 ,
126
+ end : rmeta_time,
127
+ } ,
128
+ codegen : SectionData {
129
+ start : rmeta_time,
130
+ end,
131
+ } ,
132
+ }
133
+ } else {
134
+ AggregatedSections :: OnlyTotalDuration
135
+ }
136
+ }
137
+ }
138
+
95
139
/// Periodic concurrency tracking information.
96
140
#[ derive( serde:: Serialize ) ]
97
141
struct Concurrency {
@@ -106,6 +150,39 @@ struct Concurrency {
106
150
inactive : usize ,
107
151
}
108
152
153
+ /// Postprocessed section data that has both start and an end.
154
+ #[ derive( serde:: Serialize ) ]
155
+ struct SectionData {
156
+ /// Start (relative to the start of the unit)
157
+ start : f64 ,
158
+ /// End (relative to the start of the unit)
159
+ end : f64 ,
160
+ }
161
+
162
+ impl SectionData {
163
+ fn duration ( & self ) -> f64 {
164
+ ( self . end - self . start ) . max ( 0.0 )
165
+ }
166
+ }
167
+
168
+ /// Contains post-processed data of individual compilation sections.
169
+ #[ derive( serde:: Serialize ) ]
170
+ enum AggregatedSections {
171
+ /// We know only the total duration
172
+ OnlyTotalDuration ,
173
+ /// We only know when .rmeta was generated, so we can distill frontend and codegen time.
174
+ OnlyCodegenDuration {
175
+ frontend : SectionData ,
176
+ codegen : SectionData ,
177
+ } ,
178
+ /// We know the durations of the three individual sections.
179
+ Sections {
180
+ frontend : SectionData ,
181
+ codegen : SectionData ,
182
+ linking : SectionData ,
183
+ } ,
184
+ }
185
+
109
186
impl < ' gctx > Timings < ' gctx > {
110
187
pub fn new ( bcx : & BuildContext < ' _ , ' gctx > , root_units : & [ Unit ] ) -> Timings < ' gctx > {
111
188
let has_report = |what| bcx. build_config . timing_outputs . contains ( & what) ;
@@ -476,6 +553,7 @@ impl<'gctx> Timings<'gctx> {
476
553
. enumerate ( )
477
554
. map ( |( i, ut) | ( ut. unit . clone ( ) , i) )
478
555
. collect ( ) ;
556
+
479
557
#[ derive( serde:: Serialize ) ]
480
558
struct UnitData {
481
559
i : usize ,
@@ -549,6 +627,18 @@ impl<'gctx> Timings<'gctx> {
549
627
550
628
/// Render the table of all units.
551
629
fn write_unit_table ( & self , f : & mut impl Write ) -> CargoResult < ( ) > {
630
+ let mut units: Vec < & UnitTime > = self . unit_times . iter ( ) . collect ( ) ;
631
+ units. sort_unstable_by ( |a, b| b. duration . partial_cmp ( & a. duration ) . unwrap ( ) ) ;
632
+
633
+ let has_linking_time = units
634
+ . iter ( )
635
+ . any ( |u| matches ! ( u. aggregate_sections( ) , AggregatedSections :: Sections { .. } ) ) ;
636
+ // Skip the linker column if we have no data for it
637
+ let linking_header = if has_linking_time {
638
+ "<th>Linking</th>"
639
+ } else {
640
+ ""
641
+ } ;
552
642
write ! (
553
643
f,
554
644
r#"
@@ -558,20 +648,38 @@ impl<'gctx> Timings<'gctx> {
558
648
<th></th>
559
649
<th>Unit</th>
560
650
<th>Total</th>
651
+ <th>Frontend</th>
561
652
<th>Codegen</th>
653
+ {linking_header}
562
654
<th>Features</th>
563
655
</tr>
564
656
</thead>
565
657
<tbody>
566
658
"#
567
659
) ?;
568
- let mut units: Vec < & UnitTime > = self . unit_times . iter ( ) . collect ( ) ;
569
- units. sort_unstable_by ( |a, b| b. duration . partial_cmp ( & a. duration ) . unwrap ( ) ) ;
660
+
570
661
for ( i, unit) in units. iter ( ) . enumerate ( ) {
571
- let codegen = match unit. codegen_time ( ) {
662
+ let format_duration = |section : Option < SectionData > | match section {
663
+ Some ( section) => {
664
+ let duration = section. duration ( ) ;
665
+ let pct = ( duration / unit. duration ) * 100.0 ;
666
+ format ! ( "{duration:.1}s ({:.0}%)" , pct)
667
+ }
572
668
None => "" . to_string ( ) ,
573
- Some ( ( _rt, ctime, cent) ) => format ! ( "{:.1}s ({:.0}%)" , ctime, cent) ,
574
669
} ;
670
+ let sections = unit. aggregate_sections ( ) ;
671
+ let ( frontend, codegen, linking) = match sections {
672
+ AggregatedSections :: OnlyTotalDuration => ( None , None , None ) ,
673
+ AggregatedSections :: OnlyCodegenDuration { frontend, codegen } => {
674
+ ( Some ( frontend) , Some ( codegen) , None )
675
+ }
676
+ AggregatedSections :: Sections {
677
+ frontend,
678
+ codegen,
679
+ linking,
680
+ } => ( Some ( frontend) , Some ( codegen) , Some ( linking) ) ,
681
+ } ;
682
+
575
683
let features = unit. unit . features . join ( ", " ) ;
576
684
write ! (
577
685
f,
@@ -582,13 +690,21 @@ impl<'gctx> Timings<'gctx> {
582
690
<td>{:.1}s</td>
583
691
<td>{}</td>
584
692
<td>{}</td>
693
+ {}
694
+ <td>{}</td>
585
695
</tr>
586
696
"# ,
587
697
i + 1 ,
588
698
unit. name_ver( ) ,
589
699
unit. target,
590
700
unit. duration,
591
- codegen,
701
+ format_duration( frontend) ,
702
+ format_duration( codegen) ,
703
+ if has_linking_time {
704
+ format!( "<td>{}</td>" , format_duration( linking) )
705
+ } else {
706
+ "" . to_string( )
707
+ } ,
592
708
features,
593
709
) ?;
594
710
}
@@ -598,15 +714,6 @@ impl<'gctx> Timings<'gctx> {
598
714
}
599
715
600
716
impl UnitTime {
601
- /// Returns the codegen time as (`rmeta_time`, `codegen_time`, percent of total)
602
- fn codegen_time ( & self ) -> Option < ( f64 , f64 , f64 ) > {
603
- self . rmeta_time . map ( |rmeta_time| {
604
- let ctime = self . duration - rmeta_time;
605
- let cent = ( ctime / self . duration ) * 100.0 ;
606
- ( rmeta_time, ctime, cent)
607
- } )
608
- }
609
-
610
717
fn name_ver ( & self ) -> String {
611
718
format ! ( "{} v{}" , self . unit. pkg. name( ) , self . unit. pkg. version( ) )
612
719
}
0 commit comments