diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-08-05 14:55:17 +0100 |
---|---|---|
committer | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-08-05 14:55:17 +0100 |
commit | 12a7329cb3141e8b6e719cc08f1eea1bdb3fae3a (patch) | |
tree | 4048f6a71b825dd93d7c968bc44471143d69473b | |
parent | a490f80a9c49380c5088b704047bb20b76c06e4d (diff) | |
parent | f1cfd5ec3de3de39e5423e80a35c719463c4e5c0 (diff) |
Merge #1648
1648: Optimize parsing a little r=lnicola a=lnicola
This is the change from https://github.com/rust-analyzer/rust-analyzer/issues/1643#issuecomment-517979911. In the long run we should probably take a different approach, but until then this provides a decent speed-up (10.5s vs 11.5s according to `ra_cli analysis-stats`.
EDIT: Does the profiling part make sense? I'm not sure if all parsing happens before the type inference begins or it's lazy.
Co-authored-by: Laurențiu Nicola <[email protected]>
Co-authored-by: Laurențiu Nicola <[email protected]>
-rw-r--r-- | crates/ra_cli/src/analysis_stats.rs | 6 | ||||
-rw-r--r-- | crates/ra_parser/src/parser.rs | 54 |
2 files changed, 40 insertions, 20 deletions
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs index 403aab352..7e7e6c073 100644 --- a/crates/ra_cli/src/analysis_stats.rs +++ b/crates/ra_cli/src/analysis_stats.rs | |||
@@ -52,6 +52,9 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) - | |||
52 | println!("Total modules found: {}", visited_modules.len()); | 52 | println!("Total modules found: {}", visited_modules.len()); |
53 | println!("Total declarations: {}", num_decls); | 53 | println!("Total declarations: {}", num_decls); |
54 | println!("Total functions: {}", funcs.len()); | 54 | println!("Total functions: {}", funcs.len()); |
55 | println!("Item Collection: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); | ||
56 | |||
57 | let inference_time = Instant::now(); | ||
55 | let bar = indicatif::ProgressBar::with_draw_target( | 58 | let bar = indicatif::ProgressBar::with_draw_target( |
56 | funcs.len() as u64, | 59 | funcs.len() as u64, |
57 | indicatif::ProgressDrawTarget::stderr_nohz(), | 60 | indicatif::ProgressDrawTarget::stderr_nohz(), |
@@ -112,7 +115,8 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) - | |||
112 | num_exprs_partially_unknown, | 115 | num_exprs_partially_unknown, |
113 | (num_exprs_partially_unknown * 100 / num_exprs) | 116 | (num_exprs_partially_unknown * 100 / num_exprs) |
114 | ); | 117 | ); |
115 | println!("Analysis: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); | 118 | println!("Inference: {:?}, {}", inference_time.elapsed(), ra_prof::memory_usage()); |
119 | println!("Total: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); | ||
116 | 120 | ||
117 | if memory_usage { | 121 | if memory_usage { |
118 | drop(db); | 122 | drop(db); |
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs index 159ed50df..393586561 100644 --- a/crates/ra_parser/src/parser.rs +++ b/crates/ra_parser/src/parser.rs | |||
@@ -6,7 +6,7 @@ use crate::{ | |||
6 | event::Event, | 6 | event::Event, |
7 | ParseError, | 7 | ParseError, |
8 | SyntaxKind::{self, EOF, ERROR, TOMBSTONE}, | 8 | SyntaxKind::{self, EOF, ERROR, TOMBSTONE}, |
9 | TokenSet, TokenSource, T, | 9 | Token, TokenSet, TokenSource, T, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | /// `Parser` struct provides the low-level API for | 12 | /// `Parser` struct provides the low-level API for |
@@ -87,8 +87,9 @@ impl<'t> Parser<'t> { | |||
87 | let mut i = 0; | 87 | let mut i = 0; |
88 | 88 | ||
89 | loop { | 89 | loop { |
90 | let mut kind = self.token_source.lookahead_nth(i).kind; | 90 | let token = self.token_source.lookahead_nth(i); |
91 | if let Some((composited, step)) = self.is_composite(kind, i) { | 91 | let mut kind = token.kind; |
92 | if let Some((composited, step)) = self.is_composite(token, i) { | ||
92 | kind = composited; | 93 | kind = composited; |
93 | i += step; | 94 | i += step; |
94 | } else { | 95 | } else { |
@@ -250,32 +251,47 @@ impl<'t> Parser<'t> { | |||
250 | } | 251 | } |
251 | 252 | ||
252 | /// helper function for check if it is composite. | 253 | /// helper function for check if it is composite. |
253 | fn is_composite(&self, kind: SyntaxKind, n: usize) -> Option<(SyntaxKind, usize)> { | 254 | fn is_composite(&self, first: Token, n: usize) -> Option<(SyntaxKind, usize)> { |
254 | // We assume the dollars will not occuried between | 255 | // We assume the dollars will not occuried between |
255 | // mult-byte tokens | 256 | // mult-byte tokens |
256 | 257 | ||
257 | let first = self.token_source.lookahead_nth(n); | 258 | let jn1 = first.is_jointed_to_next; |
259 | if !jn1 && first.kind != T![-] { | ||
260 | return None; | ||
261 | } | ||
262 | |||
258 | let second = self.token_source.lookahead_nth(n + 1); | 263 | let second = self.token_source.lookahead_nth(n + 1); |
264 | if first.kind == T![-] && second.kind == T![>] { | ||
265 | return Some((T![->], 2)); | ||
266 | } | ||
267 | if !jn1 { | ||
268 | return None; | ||
269 | } | ||
270 | |||
271 | match (first.kind, second.kind) { | ||
272 | (T![:], T![:]) => return Some((T![::], 2)), | ||
273 | (T![=], T![=]) => return Some((T![==], 2)), | ||
274 | (T![=], T![>]) => return Some((T![=>], 2)), | ||
275 | (T![!], T![=]) => return Some((T![!=], 2)), | ||
276 | _ => {} | ||
277 | } | ||
278 | |||
279 | if first.kind != T![.] || second.kind != T![.] { | ||
280 | return None; | ||
281 | } | ||
282 | |||
259 | let third = self.token_source.lookahead_nth(n + 2); | 283 | let third = self.token_source.lookahead_nth(n + 2); |
260 | 284 | ||
261 | let jn1 = first.is_jointed_to_next; | ||
262 | let la2 = second.kind; | ||
263 | let jn2 = second.is_jointed_to_next; | 285 | let jn2 = second.is_jointed_to_next; |
264 | let la3 = third.kind; | 286 | let la3 = third.kind; |
265 | 287 | ||
266 | match kind { | 288 | if jn2 && la3 == T![.] { |
267 | T![.] if jn1 && la2 == T![.] && jn2 && la3 == T![.] => Some((T![...], 3)), | 289 | return Some((T![...], 3)); |
268 | T![.] if jn1 && la2 == T![.] && la3 == T![=] => Some((T![..=], 3)), | 290 | } |
269 | T![.] if jn1 && la2 == T![.] => Some((T![..], 2)), | 291 | if la3 == T![=] { |
270 | 292 | return Some((T![..=], 3)); | |
271 | T![:] if jn1 && la2 == T![:] => Some((T![::], 2)), | ||
272 | T![=] if jn1 && la2 == T![=] => Some((T![==], 2)), | ||
273 | T![=] if jn1 && la2 == T![>] => Some((T![=>], 2)), | ||
274 | |||
275 | T![!] if jn1 && la2 == T![=] => Some((T![!=], 2)), | ||
276 | T![-] if la2 == T![>] => Some((T![->], 2)), | ||
277 | _ => None, | ||
278 | } | 293 | } |
294 | return Some((T![..], 2)); | ||
279 | } | 295 | } |
280 | 296 | ||
281 | fn eat_dollars(&mut self) { | 297 | fn eat_dollars(&mut self) { |