1 #![allow(non_camel_case_types)]
3 use rustc_data_structures
::sync
::Lock
;
7 use std
::time
::{Duration, Instant}
;
9 use syntax
::symbol
::{Symbol, sym}
;
10 use crate::session
::Session
;
15 // The name of the associated type for `Fn` return types.
16 pub const FN_OUTPUT_NAME
: Symbol
= sym
::Output
;
18 pub use errors
::ErrorReported
;
20 thread_local
!(static TIME_DEPTH
: Cell
<usize> = Cell
::new(0));
22 #[allow(nonstandard_style)]
23 #[derive(Clone, Debug, PartialEq, Eq)]
25 pub query
: &'
static str,
26 pub msg
: Option
<String
>,
29 /// Read the current depth of `time()` calls. This is used to
30 /// encourage indentation across threads.
31 pub fn time_depth() -> usize {
32 TIME_DEPTH
.with(|slot
| slot
.get())
35 /// Sets the current depth of `time()` calls. The idea is to call
36 /// `set_time_depth()` with the result from `time_depth()` in the
38 pub fn set_time_depth(depth
: usize) {
39 TIME_DEPTH
.with(|slot
| slot
.set(depth
));
42 pub fn time
<T
, F
>(sess
: &Session
, what
: &str, f
: F
) -> T
where
45 time_ext(sess
.time_passes(), what
, f
)
48 pub fn time_ext
<T
, F
>(do_it
: bool
, what
: &str, f
: F
) -> T
where
51 if !do_it { return f(); }
53 let old
= TIME_DEPTH
.with(|slot
| {
59 let start
= Instant
::now();
61 let dur
= start
.elapsed();
63 print_time_passes_entry(true, what
, dur
);
65 TIME_DEPTH
.with(|slot
| slot
.set(old
));
70 pub fn print_time_passes_entry(do_it
: bool
, what
: &str, dur
: Duration
) {
75 let indentation
= TIME_DEPTH
.with(|slot
| slot
.get());
77 let mem_string
= match get_resident() {
79 let mb
= n
as f64 / 1_000_000.0;
80 format
!("; rss: {}MB", mb
.round() as usize)
82 None
=> String
::new(),
84 println
!("{}time: {}{}\t{}",
85 " ".repeat(indentation
),
86 duration_to_secs_str(dur
),
91 pub use rustc_session
::utils
::duration_to_secs_str
;
93 pub fn to_readable_str(mut val
: usize) -> String
{
94 let mut groups
= vec
![];
96 let group
= val
% 1000;
101 groups
.push(group
.to_string());
104 groups
.push(format
!("{:03}", group
));
113 pub fn record_time
<T
, F
>(accu
: &Lock
<Duration
>, f
: F
) -> T
where
116 let start
= Instant
::now();
118 let duration
= start
.elapsed();
119 let mut accu
= accu
.lock();
120 *accu
= *accu
+ duration
;
126 fn get_resident() -> Option
<usize> {
130 let contents
= fs
::read("/proc/self/statm").ok()?
;
131 let contents
= String
::from_utf8(contents
).ok()?
;
132 let s
= contents
.split_whitespace().nth(field
)?
;
133 let npages
= s
.parse
::<usize>().ok()?
;
138 fn get_resident() -> Option
<usize> {
141 type HANDLE
= *mut u8;
145 #[allow(non_snake_case)]
146 struct PROCESS_MEMORY_COUNTERS
{
148 PageFaultCount
: DWORD
,
149 PeakWorkingSetSize
: size_t
,
150 WorkingSetSize
: size_t
,
151 QuotaPeakPagedPoolUsage
: size_t
,
152 QuotaPagedPoolUsage
: size_t
,
153 QuotaPeakNonPagedPoolUsage
: size_t
,
154 QuotaNonPagedPoolUsage
: size_t
,
155 PagefileUsage
: size_t
,
156 PeakPagefileUsage
: size_t
,
158 type PPROCESS_MEMORY_COUNTERS
= *mut PROCESS_MEMORY_COUNTERS
;
159 #[link(name = "psapi")]
161 fn GetCurrentProcess() -> HANDLE
;
162 fn GetProcessMemoryInfo(Process
: HANDLE
,
163 ppsmemCounters
: PPROCESS_MEMORY_COUNTERS
,
166 let mut pmc
: PROCESS_MEMORY_COUNTERS
= unsafe { mem::zeroed() }
;
167 pmc
.cb
= mem
::size_of_val(&pmc
) as DWORD
;
168 match unsafe { GetProcessMemoryInfo(GetCurrentProcess(), &mut pmc, pmc.cb) }
{
170 _
=> Some(pmc
.WorkingSetSize
as usize),
174 pub fn indent
<R
, F
>(op
: F
) -> R
where
178 // Use in conjunction with the log post-processor like `src/etc/indenter`
179 // to make debug output more readable.
182 debug
!("<< (Result = {:?})", r
);
186 pub struct Indenter
{
187 _cannot_construct_outside_of_this_module
: (),
190 impl Drop
for Indenter
{
191 fn drop(&mut self) { debug!("<<"); }
194 pub fn indenter() -> Indenter
{
196 Indenter { _cannot_construct_outside_of_this_module: () }