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 rustc_macros::HashStable;
11 use crate::session::Session;
16 // The name of the associated type for `Fn` return types.
17 pub const FN_OUTPUT_NAME: Symbol = sym::Output;
19 // Useful type to use with `Result<>` indicate that an error has already
20 // been reported to the user, so no need to continue checking.
21 #[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, HashStable)]
22 pub struct ErrorReported;
24 thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
26 #[allow(nonstandard_style)]
27 #[derive(Clone, Debug, PartialEq, Eq)]
29 pub query: &'static str,
30 pub msg: Option<String>,
33 /// Read the current depth of `time()` calls. This is used to
34 /// encourage indentation across threads.
35 pub fn time_depth() -> usize {
36 TIME_DEPTH.with(|slot| slot.get())
39 /// Sets the current depth of `time()` calls. The idea is to call
40 /// `set_time_depth()` with the result from `time_depth()` in the
42 pub fn set_time_depth(depth: usize) {
43 TIME_DEPTH.with(|slot| slot.set(depth));
46 pub fn time<T, F>(sess: &Session, what: &str, f: F) -> T where
49 time_ext(sess.time_passes(), what, f)
52 pub fn time_ext<T, F>(do_it: bool, what: &str, f: F) -> T where
55 if !do_it { return f(); }
57 let old = TIME_DEPTH.with(|slot| {
63 let start = Instant::now();
65 let dur = start.elapsed();
67 print_time_passes_entry(true, what, dur);
69 TIME_DEPTH.with(|slot| slot.set(old));
74 pub fn print_time_passes_entry(do_it: bool, what: &str, dur: Duration) {
79 let indentation = TIME_DEPTH.with(|slot| slot.get());
81 let mem_string = match get_resident() {
83 let mb = n as f64 / 1_000_000.0;
84 format!("; rss: {}MB", mb.round() as usize)
86 None => String::new(),
88 println!("{}time: {}{}\t{}",
89 " ".repeat(indentation),
90 duration_to_secs_str(dur),
95 // Hack up our own formatting for the duration to make it easier for scripts
96 // to parse (always use the same number of decimal places and the same unit).
97 pub fn duration_to_secs_str(dur: Duration) -> String {
98 const NANOS_PER_SEC: f64 = 1_000_000_000.0;
99 let secs = dur.as_secs() as f64 +
100 dur.subsec_nanos() as f64 / NANOS_PER_SEC;
102 format!("{:.3}", secs)
105 pub fn to_readable_str(mut val: usize) -> String {
106 let mut groups = vec![];
108 let group = val % 1000;
113 groups.push(group.to_string());
116 groups.push(format!("{:03}", group));
125 pub fn record_time<T, F>(accu: &Lock<Duration>, f: F) -> T where
128 let start = Instant::now();
130 let duration = start.elapsed();
131 let mut accu = accu.lock();
132 *accu = *accu + duration;
138 fn get_resident() -> Option<usize> {
142 let contents = fs::read("/proc/self/statm").ok()?;
143 let contents = String::from_utf8(contents).ok()?;
144 let s = contents.split_whitespace().nth(field)?;
145 let npages = s.parse::<usize>().ok()?;
150 fn get_resident() -> Option<usize> {
153 type HANDLE = *mut u8;
157 #[allow(non_snake_case)]
158 struct PROCESS_MEMORY_COUNTERS {
160 PageFaultCount: DWORD,
161 PeakWorkingSetSize: size_t,
162 WorkingSetSize: size_t,
163 QuotaPeakPagedPoolUsage: size_t,
164 QuotaPagedPoolUsage: size_t,
165 QuotaPeakNonPagedPoolUsage: size_t,
166 QuotaNonPagedPoolUsage: size_t,
167 PagefileUsage: size_t,
168 PeakPagefileUsage: size_t,
170 type PPROCESS_MEMORY_COUNTERS = *mut PROCESS_MEMORY_COUNTERS;
171 #[link(name = "psapi")]
173 fn GetCurrentProcess() -> HANDLE;
174 fn GetProcessMemoryInfo(Process: HANDLE,
175 ppsmemCounters: PPROCESS_MEMORY_COUNTERS,
178 let mut pmc: PROCESS_MEMORY_COUNTERS = unsafe { mem::zeroed() };
179 pmc.cb = mem::size_of_val(&pmc) as DWORD;
180 match unsafe { GetProcessMemoryInfo(GetCurrentProcess(), &mut pmc, pmc.cb) } {
182 _ => Some(pmc.WorkingSetSize as usize),
186 pub fn indent<R, F>(op: F) -> R where
190 // Use in conjunction with the log post-processor like `src/etc/indenter`
191 // to make debug output more readable.
194 debug!("<< (Result = {:?})", r);
198 pub struct Indenter {
199 _cannot_construct_outside_of_this_module: (),
202 impl Drop for Indenter {
203 fn drop(&mut self) { debug!("<<"); }
206 pub fn indenter() -> Indenter {
208 Indenter { _cannot_construct_outside_of_this_module: () }