aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-04-14 21:18:58 +0100
committerAleksey Kladov <[email protected]>2019-04-14 23:10:07 +0100
commit5b7012318cdf5fb0bb8b01319270c1b4bf0311ee (patch)
treebd6ef9c5dbc06ae9eb4cf5b5cd769c1b8e4f6f92
parentb228947b6863f5864b48bb3a7f3dcca921f58d0b (diff)
filter by time
-rw-r--r--crates/ra_lsp_server/src/main.rs25
-rw-r--r--crates/ra_prof/src/lib.rs40
-rw-r--r--docs/dev/README.md6
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;
8fn main() -> Result<()> { 8fn 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 {
101pub struct Filter { 102pub struct Filter {
102 depth: usize, 103 depth: usize,
103 allowed: Vec<String>, 104 allowed: Vec<String>,
105 cutoff: Duration,
104} 106}
105 107
106impl Filter { 108impl 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
141static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false); 169static 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.
105Inside rust-analyzer, we use the standard `log` crate for logging, and 105Inside 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
107with `env_logger`), but the stderr itself is processed by VS Code. To mirror 107with `env_logger`), but the stderr itself is processed by VS Code. To mirror
108logs to a `./log` directory, set `RA_INTERNAL_MODE=1` environmental variable. 108logs to a `./log` directory, set `RA_LOG_DIR=1` environmental variable.
109 109
110To see stderr in the running VS Code instance, go to the "Output" tab of the 110To see stderr in the running VS Code instance, go to the "Output" tab of the
111panel and select `rust-analyzer`. This shows `eprintln!` as well. Note that 111panel 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```
144RA_PROFILE=* // dump everything 144RA_PROFILE=* // dump everything
145RA_PROFILE=foo|bar|baz // enabled only selected entries 145RA_PROFILE=foo|bar|baz // enabled only selected entries
146RA_PROFILE=*@3 // dump everything, up to depth 3 146RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms
147``` 147```
148
149In particular, I have `export RA_PROFILE='*>10' in my shell profile.