]> git.proxmox.com Git - rustc.git/blame - src/librustc/util/common.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc / util / common.rs
CommitLineData
1a4d82fc
JJ
1#![allow(non_camel_case_types)]
2
e74abb32 3use rustc_data_structures::sync::Lock;
83c7162d 4
e74abb32 5use std::cell::Cell;
85aaf69f 6use std::fmt::Debug;
9e0c209e 7use std::time::{Duration, Instant};
223e47cc 8
48663c56 9use syntax::symbol::{Symbol, sym};
9fa01778 10use crate::session::Session;
041b39d2 11
416331ca
XL
12#[cfg(test)]
13mod tests;
14
dc9dc135 15// The name of the associated type for `Fn` return types.
48663c56 16pub const FN_OUTPUT_NAME: Symbol = sym::Output;
85aaf69f 17
60c5eb7d 18pub use errors::ErrorReported;
1a4d82fc 19
32a655c1
SL
20thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
21
b7449926 22#[allow(nonstandard_style)]
83c7162d
XL
23#[derive(Clone, Debug, PartialEq, Eq)]
24pub struct QueryMsg {
25 pub query: &'static str,
26 pub msg: Option<String>,
27}
28
32a655c1
SL
29/// Read the current depth of `time()` calls. This is used to
30/// encourage indentation across threads.
31pub fn time_depth() -> usize {
32 TIME_DEPTH.with(|slot| slot.get())
33}
34
9fa01778 35/// Sets the current depth of `time()` calls. The idea is to call
32a655c1
SL
36/// `set_time_depth()` with the result from `time_depth()` in the
37/// parent thread.
38pub fn set_time_depth(depth: usize) {
39 TIME_DEPTH.with(|slot| slot.set(depth));
40}
41
0531ce1d
XL
42pub fn time<T, F>(sess: &Session, what: &str, f: F) -> T where
43 F: FnOnce() -> T,
44{
e74abb32 45 time_ext(sess.time_passes(), what, f)
0531ce1d
XL
46}
47
e74abb32 48pub fn time_ext<T, F>(do_it: bool, what: &str, f: F) -> T where
e9174d1e 49 F: FnOnce() -> T,
1a4d82fc 50{
e9174d1e 51 if !do_it { return f(); }
1a4d82fc 52
32a655c1 53 let old = TIME_DEPTH.with(|slot| {
1a4d82fc
JJ
54 let r = slot.get();
55 slot.set(r + 1);
56 r
57 });
58
92a42be0
SL
59 let start = Instant::now();
60 let rv = f();
61 let dur = start.elapsed();
3b2f2976 62
416331ca 63 print_time_passes_entry(true, what, dur);
3b2f2976
XL
64
65 TIME_DEPTH.with(|slot| slot.set(old));
66
67 rv
68}
69
70pub fn print_time_passes_entry(do_it: bool, what: &str, dur: Duration) {
71 if !do_it {
72 return
73 }
74
3b2f2976 75 let indentation = TIME_DEPTH.with(|slot| slot.get());
223e47cc 76
c1a9b12d
SL
77 let mem_string = match get_resident() {
78 Some(n) => {
79 let mb = n as f64 / 1_000_000.0;
80 format!("; rss: {}MB", mb.round() as usize)
81 }
b7449926 82 None => String::new(),
c1a9b12d 83 };
9e0c209e 84 println!("{}time: {}{}\t{}",
8faf50e0 85 " ".repeat(indentation),
9e0c209e
SL
86 duration_to_secs_str(dur),
87 mem_string,
88 what);
223e47cc
LB
89}
90
60c5eb7d 91pub use rustc_session::utils::duration_to_secs_str;
9e0c209e 92
c30ab7b3
SL
93pub fn to_readable_str(mut val: usize) -> String {
94 let mut groups = vec![];
95 loop {
96 let group = val % 1000;
97
98 val /= 1000;
99
100 if val == 0 {
8faf50e0 101 groups.push(group.to_string());
cc61c64b 102 break;
c30ab7b3
SL
103 } else {
104 groups.push(format!("{:03}", group));
105 }
106 }
107
108 groups.reverse();
109
110 groups.join("_")
111}
112
83c7162d 113pub fn record_time<T, F>(accu: &Lock<Duration>, f: F) -> T where
9e0c209e
SL
114 F: FnOnce() -> T,
115{
116 let start = Instant::now();
117 let rv = f();
118 let duration = start.elapsed();
83c7162d
XL
119 let mut accu = accu.lock();
120 *accu = *accu + duration;
9e0c209e
SL
121 rv
122}
123
c1a9b12d
SL
124// Memory reporting
125#[cfg(unix)]
126fn get_resident() -> Option<usize> {
2c00a5a8 127 use std::fs;
c1a9b12d 128
e9174d1e 129 let field = 1;
0531ce1d
XL
130 let contents = fs::read("/proc/self/statm").ok()?;
131 let contents = String::from_utf8(contents).ok()?;
ff7c6d11
XL
132 let s = contents.split_whitespace().nth(field)?;
133 let npages = s.parse::<usize>().ok()?;
e9174d1e 134 Some(npages * 4096)
c1a9b12d
SL
135}
136
c1a9b12d 137#[cfg(windows)]
e9174d1e 138fn get_resident() -> Option<usize> {
92a42be0
SL
139 type BOOL = i32;
140 type DWORD = u32;
141 type HANDLE = *mut u8;
142 use libc::size_t;
c1a9b12d 143 use std::mem;
cc61c64b
XL
144 #[repr(C)]
145 #[allow(non_snake_case)]
c1a9b12d
SL
146 struct PROCESS_MEMORY_COUNTERS {
147 cb: DWORD,
148 PageFaultCount: DWORD,
92a42be0
SL
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,
c1a9b12d
SL
157 }
158 type PPROCESS_MEMORY_COUNTERS = *mut PROCESS_MEMORY_COUNTERS;
159 #[link(name = "psapi")]
160 extern "system" {
92a42be0 161 fn GetCurrentProcess() -> HANDLE;
c1a9b12d
SL
162 fn GetProcessMemoryInfo(Process: HANDLE,
163 ppsmemCounters: PPROCESS_MEMORY_COUNTERS,
164 cb: DWORD) -> BOOL;
165 }
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) } {
169 0 => None,
170 _ => Some(pmc.WorkingSetSize as usize),
171 }
172}
173
1a4d82fc 174pub fn indent<R, F>(op: F) -> R where
85aaf69f 175 R: Debug,
1a4d82fc
JJ
176 F: FnOnce() -> R,
177{
223e47cc
LB
178 // Use in conjunction with the log post-processor like `src/etc/indenter`
179 // to make debug output more readable.
180 debug!(">>");
181 let r = op();
1a4d82fc 182 debug!("<< (Result = {:?})", r);
223e47cc
LB
183 r
184}
185
1a4d82fc 186pub struct Indenter {
cc61c64b 187 _cannot_construct_outside_of_this_module: (),
223e47cc
LB
188}
189
1a4d82fc
JJ
190impl Drop for Indenter {
191 fn drop(&mut self) { debug!("<<"); }
223e47cc
LB
192}
193
1a4d82fc 194pub fn indenter() -> Indenter {
223e47cc 195 debug!(">>");
1a4d82fc 196 Indenter { _cannot_construct_outside_of_this_module: () }
223e47cc 197}