@@ -20,7 +20,7 @@ use std::process::{
20
20
Child , ChildStderr , ChildStdout , Command , CommandArgs , CommandEnvs , ExitStatus , Output , Stdio ,
21
21
} ;
22
22
use std:: sync:: { Arc , Mutex } ;
23
- use std:: time:: { Duration , Instant } ;
23
+ use std:: time:: { Duration , Instant , SystemTime , UNIX_EPOCH } ;
24
24
25
25
use build_helper:: ci:: CiEnv ;
26
26
use build_helper:: drop_bomb:: DropBomb ;
@@ -74,7 +74,16 @@ pub struct CommandFingerprint {
74
74
args : Vec < OsString > ,
75
75
envs : Vec < ( OsString , Option < OsString > ) > ,
76
76
cwd : Option < PathBuf > ,
77
- short_cmd : String ,
77
+ }
78
+
79
+ impl FormatShortCmd for CommandFingerprint {
80
+ fn format_short_cmd ( & self ) -> String {
81
+ let program = Path :: new ( & self . program ) ;
82
+ let mut line = vec ! [ program. file_name( ) . unwrap( ) . to_str( ) . unwrap( ) . to_owned( ) ] ;
83
+ line. extend ( self . args . iter ( ) . map ( |arg| arg. to_string_lossy ( ) . into_owned ( ) ) ) ;
84
+ line. extend ( self . cwd . iter ( ) . map ( |p| p. to_string_lossy ( ) . into_owned ( ) ) ) ;
85
+ line. join ( " " )
86
+ }
78
87
}
79
88
80
89
#[ derive( Default , Clone ) ]
@@ -92,15 +101,15 @@ impl CommandProfiler {
92
101
let mut stats = self . stats . lock ( ) . unwrap ( ) ;
93
102
let entry = stats. entry ( key) . or_default ( ) ;
94
103
entry. traces . push ( ExecutionTrace :: Executed {
95
- timestamp : start_time ,
104
+ timestamp : SystemTime :: now ( ) ,
96
105
duration : start_time. elapsed ( ) ,
97
106
} ) ;
98
107
}
99
108
100
109
pub fn record_cache_hit ( & self , key : CommandFingerprint ) {
101
110
let mut stats = self . stats . lock ( ) . unwrap ( ) ;
102
111
let entry = stats. entry ( key) . or_default ( ) ;
103
- entry. traces . push ( ExecutionTrace :: CacheHit { timestamp : Instant :: now ( ) } ) ;
112
+ entry. traces . push ( ExecutionTrace :: CacheHit { timestamp : SystemTime :: now ( ) } ) ;
104
113
}
105
114
106
115
pub fn report_summary ( & self ) {
@@ -118,36 +127,48 @@ impl CommandProfiler {
118
127
let mut writer = BufWriter :: new ( file) ;
119
128
let stats = self . stats . lock ( ) . unwrap ( ) ;
120
129
121
- for ( key, profile) in stats. iter ( ) {
122
- writeln ! ( writer, "Command: {:?}" , key. short_cmd) . unwrap ( ) ;
130
+ let mut entries: Vec < _ > = stats
131
+ . iter ( )
132
+ . map ( |( key, profile) | {
133
+ let max_duration = profile
134
+ . traces
135
+ . iter ( )
136
+ . filter_map ( |trace| match trace {
137
+ ExecutionTrace :: Executed { duration, .. } => Some ( * duration) ,
138
+ _ => None ,
139
+ } )
140
+ . max ( ) ;
141
+
142
+ ( key, profile, max_duration)
143
+ } )
144
+ . collect ( ) ;
145
+
146
+ entries. sort_by ( |a, b| b. 2 . cmp ( & a. 2 ) ) ;
147
+
148
+ for ( key, profile, max_duration) in entries {
149
+ writeln ! ( writer, "Command: {:?}" , key. format_short_cmd( ) ) . unwrap ( ) ;
123
150
124
151
let mut hits = 0 ;
125
152
let mut runs = 0 ;
126
- let mut max_duration: Option < Duration > = None ;
127
153
128
154
for trace in & profile. traces {
129
155
match trace {
130
156
ExecutionTrace :: CacheHit { timestamp } => {
131
157
hits += 1 ;
132
- writeln ! ( writer, " - Cache hit at: {:?}" , timestamp) . unwrap ( ) ;
158
+ let time = timestamp. duration_since ( UNIX_EPOCH ) . unwrap ( ) ;
159
+ writeln ! ( writer, " - Cache hit at: {time:?}" ) . unwrap ( ) ;
133
160
}
134
161
ExecutionTrace :: Executed { duration, timestamp } => {
135
162
runs += 1 ;
136
- if max_duration. is_none_or ( |d| * duration > d) {
137
- max_duration = Some ( * duration) ;
138
- }
139
- writeln ! (
140
- writer,
141
- " - Executed at: {:?}, duration: {:.2?}" ,
142
- timestamp, duration
143
- )
144
- . unwrap ( ) ;
163
+ let time = timestamp. duration_since ( UNIX_EPOCH ) . unwrap ( ) ;
164
+ writeln ! ( writer, " - Executed at: {time:?}, duration: {duration:.2?}" )
165
+ . unwrap ( ) ;
145
166
}
146
167
}
147
168
}
148
169
149
170
let duration_str = match max_duration {
150
- Some ( d) => format ! ( "{:.2?}" , d ) ,
171
+ Some ( d) => format ! ( "{d :.2?}" ) ,
151
172
None => "-" . into ( ) ,
152
173
} ;
153
174
@@ -158,15 +179,14 @@ impl CommandProfiler {
158
179
. unwrap ( ) ;
159
180
}
160
181
161
- // Print a message to user
162
182
println ! ( "Command profiler report saved to {filename}" ) ;
163
183
}
164
184
}
165
185
166
186
#[ derive( Clone ) ]
167
187
pub enum ExecutionTrace {
168
- CacheHit { timestamp : Instant } ,
169
- Executed { timestamp : Instant , duration : Duration } ,
188
+ CacheHit { timestamp : SystemTime } ,
189
+ Executed { timestamp : SystemTime , duration : Duration } ,
170
190
}
171
191
172
192
/// Wrapper around `std::process::Command`.
@@ -351,7 +371,6 @@ impl<'a> BootstrapCommand {
351
371
. map ( |( k, v) | ( k. to_os_string ( ) , v. map ( |val| val. to_os_string ( ) ) ) )
352
372
. collect ( ) ,
353
373
cwd : command. get_current_dir ( ) . map ( Path :: to_path_buf) ,
354
- short_cmd : command. format_short_cmd ( ) ,
355
374
}
356
375
}
357
376
}
@@ -501,12 +520,14 @@ pub trait FormatShortCmd {
501
520
fn format_short_cmd ( & self ) -> String ;
502
521
}
503
522
523
+ #[ cfg( feature = "tracing" ) ]
504
524
impl FormatShortCmd for BootstrapCommand {
505
525
fn format_short_cmd ( & self ) -> String {
506
526
self . command . format_short_cmd ( )
507
527
}
508
528
}
509
529
530
+ #[ cfg( feature = "tracing" ) ]
510
531
impl FormatShortCmd for Command {
511
532
fn format_short_cmd ( & self ) -> String {
512
533
let program = Path :: new ( self . get_program ( ) ) ;
0 commit comments