@@ -161,16 +161,24 @@ fn main() {
161161 cmd. status ( ) . expect ( & errmsg)
162162 } ;
163163
164- if env:: var_os ( "RUSTC_PRINT_STEP_TIMINGS" ) . is_some ( ) {
164+ if env:: var_os ( "RUSTC_PRINT_STEP_TIMINGS" ) . is_some ( )
165+ || env:: var_os ( "RUSTC_PRINT_STEP_RUSAGE" ) . is_some ( )
166+ {
165167 if let Some ( crate_name) = crate_name {
166168 let dur = start. elapsed ( ) ;
167169 let is_test = args. iter ( ) . any ( |a| a == "--test" ) ;
170+ // If the user requested resource usage data, then
171+ // include that in addition to the timing output.
172+ let rusage_data =
173+ env:: var_os ( "RUSTC_PRINT_STEP_RUSAGE" ) . and_then ( |_| format_rusage_data ( ) ) ;
168174 eprintln ! (
169- "[RUSTC-TIMING] {} test:{} {}.{:03}" ,
175+ "[RUSTC-TIMING] {} test:{} {}.{:03}{}{} " ,
170176 crate_name,
171177 is_test,
172178 dur. as_secs( ) ,
173- dur. subsec_millis( )
179+ dur. subsec_millis( ) ,
180+ if rusage_data. is_some( ) { " " } else { "" } ,
181+ rusage_data. unwrap_or( String :: new( ) ) ,
174182 ) ;
175183 }
176184 }
@@ -198,3 +206,71 @@ fn main() {
198206 }
199207 }
200208}
209+
210+ #[ cfg( not( unix) ) ]
211+ /// getrusage is not available on non-unix platforms. So for now, we do not
212+ /// bother trying to make a shim for it.
213+ fn format_rusage_data ( ) -> Option < String > {
214+ None
215+ }
216+
217+ #[ cfg( unix) ]
218+ /// Tries to build a string with human readable data for several of the rusage
219+ /// fields. Note that we are focusing mainly on data that we believe to be
220+ /// supplied on Linux (the `rusage` struct has other fields in it but they are
221+ /// currently unsupported by Linux).
222+ fn format_rusage_data ( ) -> Option < String > {
223+ let rusage: libc:: rusage = unsafe {
224+ let mut recv = std:: mem:: zeroed ( ) ;
225+ // -1 is RUSAGE_CHILDREN, which means to get the rusage for all children
226+ // (and grandchildren, etc) processes that have respectively terminated
227+ // and been waited for.
228+ let retval = libc:: getrusage ( -1 , & mut recv) ;
229+ if retval != 0 {
230+ return None ;
231+ }
232+ recv
233+ } ;
234+ // Mac OS X reports the maxrss in bytes, not kb.
235+ let divisor = if env:: consts:: OS == "macos" { 1024 } else { 1 } ;
236+ let maxrss = rusage. ru_maxrss + ( divisor - 1 ) / divisor;
237+
238+ let mut init_str = format ! (
239+ "user: {USER_SEC}.{USER_USEC:03} \
240+ sys: {SYS_SEC}.{SYS_USEC:03} \
241+ max rss (kb): {MAXRSS}",
242+ USER_SEC = rusage. ru_utime. tv_sec,
243+ USER_USEC = rusage. ru_utime. tv_usec,
244+ SYS_SEC = rusage. ru_stime. tv_sec,
245+ SYS_USEC = rusage. ru_stime. tv_usec,
246+ MAXRSS = maxrss
247+ ) ;
248+
249+ // The remaining rusage stats vary in platform support. So we treat
250+ // uniformly zero values in each category as "not worth printing", since it
251+ // either means no events of that type occurred, or that the platform
252+ // does not support it.
253+
254+ let minflt = rusage. ru_minflt ;
255+ let majflt = rusage. ru_majflt ;
256+ if minflt != 0 || majflt != 0 {
257+ init_str. push_str ( & format ! ( " page reclaims: {} page faults: {}" , minflt, majflt) ) ;
258+ }
259+
260+ let inblock = rusage. ru_inblock ;
261+ let oublock = rusage. ru_oublock ;
262+ if inblock != 0 || oublock != 0 {
263+ init_str. push_str ( & format ! ( " fs block inputs: {} fs block outputs: {}" , inblock, oublock) ) ;
264+ }
265+
266+ let nvcsw = rusage. ru_nvcsw ;
267+ let nivcsw = rusage. ru_nivcsw ;
268+ if nvcsw != 0 || nivcsw != 0 {
269+ init_str. push_str ( & format ! (
270+ " voluntary ctxt switches: {} involuntary ctxt switches: {}" ,
271+ nvcsw, nivcsw
272+ ) ) ;
273+ }
274+
275+ return Some ( init_str) ;
276+ }
0 commit comments