diff options
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 25 | ||||
-rw-r--r-- | crates/ra_prof/src/lib.rs | 40 | ||||
-rw-r--r-- | docs/dev/README.md | 6 |
3 files changed, 43 insertions, 28 deletions
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index 28f9985b6..b0b70df5c 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs | |||
@@ -8,31 +8,14 @@ use ra_prof; | |||
8 | fn main() -> Result<()> { | 8 | fn main() -> Result<()> { |
9 | std::env::set_var("RUST_BACKTRACE", "short"); | 9 | std::env::set_var("RUST_BACKTRACE", "short"); |
10 | let logger = Logger::with_env_or_str("error").duplicate_to_stderr(Duplicate::All); | 10 | let logger = Logger::with_env_or_str("error").duplicate_to_stderr(Duplicate::All); |
11 | match std::env::var("RA_INTERNAL_MODE") { | 11 | match std::env::var("RA_LOG_DIR") { |
12 | Ok(ref v) if v == "1" => logger.log_to_file().directory("log").start()?, | 12 | Ok(ref v) if v == "1" => logger.log_to_file().directory("log").start()?, |
13 | _ => logger.start()?, | 13 | _ => logger.start()?, |
14 | }; | 14 | }; |
15 | // Filtering syntax | 15 | ra_prof::set_filter(match std::env::var("RA_PROFILE") { |
16 | // env RA_PROFILE=* // dump everything | 16 | Ok(spec) => ra_prof::Filter::from_spec(&spec), |
17 | // env RA_PROFILE=foo|bar|baz // enabled only selected entries | ||
18 | // env RA_PROFILE=*@3 // dump everything, up to depth 3 | ||
19 | let filter = match std::env::var("RA_PROFILE") { | ||
20 | Ok(p) => { | ||
21 | let mut p = p.as_str(); | ||
22 | let depth = if let Some(idx) = p.rfind("@") { | ||
23 | let depth: usize = p[idx + 1..].parse().expect("invalid profile depth"); | ||
24 | p = &p[..idx]; | ||
25 | depth | ||
26 | } else { | ||
27 | 999 | ||
28 | }; | ||
29 | let allowed = | ||
30 | if p == "*" { Vec::new() } else { p.split(";").map(String::from).collect() }; | ||
31 | ra_prof::Filter::new(depth, allowed) | ||
32 | } | ||
33 | Err(_) => ra_prof::Filter::disabled(), | 17 | Err(_) => ra_prof::Filter::disabled(), |
34 | }; | 18 | }); |
35 | ra_prof::set_filter(filter); | ||
36 | log::info!("lifecycle: server started"); | 19 | log::info!("lifecycle: server started"); |
37 | match ::std::panic::catch_unwind(main_inner) { | 20 | match ::std::panic::catch_unwind(main_inner) { |
38 | Ok(res) => { | 21 | Ok(res) => { |
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index c7c21b6d2..999cc61f0 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs | |||
@@ -27,7 +27,8 @@ pub fn set_filter(f: Filter) { | |||
27 | PROFILING_ENABLED.store(f.depth > 0, Ordering::SeqCst); | 27 | PROFILING_ENABLED.store(f.depth > 0, Ordering::SeqCst); |
28 | let set = HashSet::from_iter(f.allowed.iter().cloned()); | 28 | let set = HashSet::from_iter(f.allowed.iter().cloned()); |
29 | let mut old = FILTER.write().unwrap(); | 29 | let mut old = FILTER.write().unwrap(); |
30 | let filter_data = FilterData { depth: f.depth, allowed: set, version: old.version + 1 }; | 30 | let filter_data = |
31 | FilterData { depth: f.depth, allowed: set, cutoff: f.cutoff, version: old.version + 1 }; | ||
31 | *old = filter_data; | 32 | *old = filter_data; |
32 | } | 33 | } |
33 | 34 | ||
@@ -101,15 +102,41 @@ pub struct Profiler { | |||
101 | pub struct Filter { | 102 | pub struct Filter { |
102 | depth: usize, | 103 | depth: usize, |
103 | allowed: Vec<String>, | 104 | allowed: Vec<String>, |
105 | cutoff: Duration, | ||
104 | } | 106 | } |
105 | 107 | ||
106 | impl Filter { | 108 | impl Filter { |
109 | // Filtering syntax | ||
110 | // env RA_PROFILE=* // dump everything | ||
111 | // env RA_PROFILE=foo|bar|baz // enabled only selected entries | ||
112 | // env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms | ||
113 | pub fn from_spec(mut spec: &str) -> Filter { | ||
114 | let cutoff = if let Some(idx) = spec.rfind(">") { | ||
115 | let cutoff = spec[idx + 1..].parse().expect("invalid profile cutoff"); | ||
116 | spec = &spec[..idx]; | ||
117 | Duration::from_millis(cutoff) | ||
118 | } else { | ||
119 | Duration::new(0, 0) | ||
120 | }; | ||
121 | |||
122 | let depth = if let Some(idx) = spec.rfind("@") { | ||
123 | let depth: usize = spec[idx + 1..].parse().expect("invalid profile depth"); | ||
124 | spec = &spec[..idx]; | ||
125 | depth | ||
126 | } else { | ||
127 | 999 | ||
128 | }; | ||
129 | let allowed = | ||
130 | if spec == "*" { Vec::new() } else { spec.split("|").map(String::from).collect() }; | ||
131 | Filter::new(depth, allowed, cutoff) | ||
132 | } | ||
133 | |||
107 | pub fn disabled() -> Filter { | 134 | pub fn disabled() -> Filter { |
108 | Filter::new(0, Vec::new()) | 135 | Filter::new(0, Vec::new(), Duration::new(0, 0)) |
109 | } | 136 | } |
110 | 137 | ||
111 | pub fn new(depth: usize, allowed: Vec<String>) -> Filter { | 138 | pub fn new(depth: usize, allowed: Vec<String>, cutoff: Duration) -> Filter { |
112 | Filter { depth, allowed } | 139 | Filter { depth, allowed, cutoff } |
113 | } | 140 | } |
114 | } | 141 | } |
115 | 142 | ||
@@ -136,6 +163,7 @@ struct FilterData { | |||
136 | depth: usize, | 163 | depth: usize, |
137 | version: usize, | 164 | version: usize, |
138 | allowed: HashSet<String>, | 165 | allowed: HashSet<String>, |
166 | cutoff: Duration, | ||
139 | } | 167 | } |
140 | 168 | ||
141 | static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false); | 169 | static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false); |
@@ -159,7 +187,9 @@ impl Drop for Profiler { | |||
159 | stack.messages.push(Message { level, duration, message }); | 187 | stack.messages.push(Message { level, duration, message }); |
160 | if level == 0 { | 188 | if level == 0 { |
161 | let stdout = stderr(); | 189 | let stdout = stderr(); |
162 | print(0, &stack.messages, &mut stdout.lock()); | 190 | if duration >= stack.filter_data.cutoff { |
191 | print(0, &stack.messages, &mut stdout.lock()); | ||
192 | } | ||
163 | stack.messages.clear(); | 193 | stack.messages.clear(); |
164 | } | 194 | } |
165 | }); | 195 | }); |
diff --git a/docs/dev/README.md b/docs/dev/README.md index 7fb5886c9..d34ff96c8 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -105,7 +105,7 @@ figure out where logs go. | |||
105 | Inside rust-analyzer, we use the standard `log` crate for logging, and | 105 | Inside rust-analyzer, we use the standard `log` crate for logging, and |
106 | `flexi_logger` for logging frotend. By default, log goes to stderr (the same as | 106 | `flexi_logger` for logging frotend. By default, log goes to stderr (the same as |
107 | with `env_logger`), but the stderr itself is processed by VS Code. To mirror | 107 | with `env_logger`), but the stderr itself is processed by VS Code. To mirror |
108 | logs to a `./log` directory, set `RA_INTERNAL_MODE=1` environmental variable. | 108 | logs to a `./log` directory, set `RA_LOG_DIR=1` environmental variable. |
109 | 109 | ||
110 | To see stderr in the running VS Code instance, go to the "Output" tab of the | 110 | To see stderr in the running VS Code instance, go to the "Output" tab of the |
111 | panel and select `rust-analyzer`. This shows `eprintln!` as well. Note that | 111 | panel and select `rust-analyzer`. This shows `eprintln!` as well. Note that |
@@ -143,5 +143,7 @@ We have a built-in hierarchical profiler, you can enable it by using `RA_PROF` e | |||
143 | ``` | 143 | ``` |
144 | RA_PROFILE=* // dump everything | 144 | RA_PROFILE=* // dump everything |
145 | RA_PROFILE=foo|bar|baz // enabled only selected entries | 145 | RA_PROFILE=foo|bar|baz // enabled only selected entries |
146 | RA_PROFILE=*@3 // dump everything, up to depth 3 | 146 | RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms |
147 | ``` | 147 | ``` |
148 | |||
149 | In particular, I have `export RA_PROFILE='*>10' in my shell profile. | ||