diff options
author | Aleksey Kladov <[email protected]> | 2019-06-16 17:19:38 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-06-16 17:45:05 +0100 |
commit | 6314e62cfb06ea7bbe5f530f2824010be0ffa4c7 (patch) | |
tree | 022742121ea273b6e90f6fbfa342660f46e9f68e /crates/ra_batch/src | |
parent | b81caed43f1886024ededad41a1baa8a03f1d2f4 (diff) |
add analysis-bench to benchmark incremental analysis
Can be used like this:
```
$ cargo run --release -p ra_cli -- \
analysis-bench ../chalk/ \
--complete ../chalk/chalk-engine/src/logic.rs:94:0
loading: 225.970093ms
from scratch: 8.492373325s
no change: 445.265µs
trivial change: 95.631242ms
```
Or like this:
```
$ cargo run --release -p ra_cli -- \
analysis-bench ../chalk/ \
--highlight ../chalk/chalk-engine/src/logic.rs
loading: 209.873484ms
from scratch: 9.504916942s
no change: 7.731119ms
trivial change: 124.984039ms
```
"from scratch" includes initial analysis of the relevant bits of the
project
"no change" just asks the same question for the second time. It
measures overhead on assembling the answer outside of salsa.
"trivial change" doesn't do an actual salsa change, it just advances
the revision. This test how fast is salsa at validating things.
Diffstat (limited to 'crates/ra_batch/src')
-rw-r--r-- | crates/ra_batch/src/lib.rs | 42 | ||||
-rw-r--r-- | crates/ra_batch/src/vfs_filter.rs | 108 |
2 files changed, 79 insertions, 71 deletions
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs index fa244e86c..43d3fb7e3 100644 --- a/crates/ra_batch/src/lib.rs +++ b/crates/ra_batch/src/lib.rs | |||
@@ -8,7 +8,7 @@ use ra_db::{ | |||
8 | CrateGraph, FileId, SourceRootId, | 8 | CrateGraph, FileId, SourceRootId, |
9 | }; | 9 | }; |
10 | use ra_ide_api::{AnalysisHost, AnalysisChange}; | 10 | use ra_ide_api::{AnalysisHost, AnalysisChange}; |
11 | use ra_project_model::ProjectWorkspace; | 11 | use ra_project_model::{ProjectWorkspace, ProjectRoot}; |
12 | use ra_vfs::{Vfs, VfsChange}; | 12 | use ra_vfs::{Vfs, VfsChange}; |
13 | use vfs_filter::IncludeRustFiles; | 13 | use vfs_filter::IncludeRustFiles; |
14 | 14 | ||
@@ -21,13 +21,11 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId { | |||
21 | SourceRootId(r.0) | 21 | SourceRootId(r.0) |
22 | } | 22 | } |
23 | 23 | ||
24 | pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, Vec<SourceRootId>)> { | 24 | pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, ProjectRoot>)> { |
25 | let root = std::env::current_dir()?.join(root); | 25 | let root = std::env::current_dir()?.join(root); |
26 | let ws = ProjectWorkspace::discover(root.as_ref())?; | 26 | let ws = ProjectWorkspace::discover(root.as_ref())?; |
27 | let mut roots = Vec::new(); | 27 | let project_roots = ws.to_roots(); |
28 | roots.push(IncludeRustFiles::member(root.clone())); | 28 | let (mut vfs, roots) = Vfs::new(IncludeRustFiles::from_roots(project_roots.clone()).collect()); |
29 | roots.extend(IncludeRustFiles::from_roots(ws.to_roots())); | ||
30 | let (mut vfs, roots) = Vfs::new(roots); | ||
31 | let crate_graph = ws.to_crate_graph(&mut |path: &Path| { | 29 | let crate_graph = ws.to_crate_graph(&mut |path: &Path| { |
32 | let vfs_file = vfs.load(path); | 30 | let vfs_file = vfs.load(path); |
33 | log::debug!("vfs file {:?} -> {:?}", path, vfs_file); | 31 | log::debug!("vfs file {:?} -> {:?}", path, vfs_file); |
@@ -35,17 +33,27 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, Vec<SourceRootId>)> { | |||
35 | }); | 33 | }); |
36 | log::debug!("crate graph: {:?}", crate_graph); | 34 | log::debug!("crate graph: {:?}", crate_graph); |
37 | 35 | ||
38 | let local_roots = roots | 36 | let source_roots = roots |
39 | .into_iter() | 37 | .iter() |
40 | .filter(|r| vfs.root2path(*r).starts_with(&root)) | 38 | .map(|&vfs_root| { |
41 | .map(vfs_root_to_id) | 39 | let source_root_id = vfs_root_to_id(vfs_root); |
42 | .collect(); | 40 | let project_root = project_roots |
43 | 41 | .iter() | |
44 | let host = load(root.as_path(), crate_graph, &mut vfs); | 42 | .find(|it| it.path() == &vfs.root2path(vfs_root)) |
45 | Ok((host, local_roots)) | 43 | .unwrap() |
44 | .clone(); | ||
45 | (source_root_id, project_root) | ||
46 | }) | ||
47 | .collect::<FxHashMap<_, _>>(); | ||
48 | let host = load(&source_roots, crate_graph, &mut vfs); | ||
49 | Ok((host, source_roots)) | ||
46 | } | 50 | } |
47 | 51 | ||
48 | pub fn load(project_root: &Path, crate_graph: CrateGraph, vfs: &mut Vfs) -> AnalysisHost { | 52 | pub fn load( |
53 | source_roots: &FxHashMap<SourceRootId, ProjectRoot>, | ||
54 | crate_graph: CrateGraph, | ||
55 | vfs: &mut Vfs, | ||
56 | ) -> AnalysisHost { | ||
49 | let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); | 57 | let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); |
50 | let mut host = AnalysisHost::new(lru_cap); | 58 | let mut host = AnalysisHost::new(lru_cap); |
51 | let mut analysis_change = AnalysisChange::new(); | 59 | let mut analysis_change = AnalysisChange::new(); |
@@ -60,8 +68,8 @@ pub fn load(project_root: &Path, crate_graph: CrateGraph, vfs: &mut Vfs) -> Anal | |||
60 | for change in vfs.commit_changes() { | 68 | for change in vfs.commit_changes() { |
61 | match change { | 69 | match change { |
62 | VfsChange::AddRoot { root, files } => { | 70 | VfsChange::AddRoot { root, files } => { |
63 | let is_local = vfs.root2path(root).starts_with(&project_root); | ||
64 | let source_root_id = vfs_root_to_id(root); | 71 | let source_root_id = vfs_root_to_id(root); |
72 | let is_local = source_roots[&source_root_id].is_member(); | ||
65 | log::debug!( | 73 | log::debug!( |
66 | "loaded source root {:?} with path {:?}", | 74 | "loaded source root {:?} with path {:?}", |
67 | source_root_id, | 75 | source_root_id, |
@@ -106,7 +114,7 @@ mod tests { | |||
106 | let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); | 114 | let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); |
107 | let (host, roots) = load_cargo(path).unwrap(); | 115 | let (host, roots) = load_cargo(path).unwrap(); |
108 | let mut n_crates = 0; | 116 | let mut n_crates = 0; |
109 | for root in roots { | 117 | for (root, _) in roots { |
110 | for _krate in Crate::source_root_crates(host.raw_database(), root) { | 118 | for _krate in Crate::source_root_crates(host.raw_database(), root) { |
111 | n_crates += 1; | 119 | n_crates += 1; |
112 | } | 120 | } |
diff --git a/crates/ra_batch/src/vfs_filter.rs b/crates/ra_batch/src/vfs_filter.rs index dd20c1203..8552ac999 100644 --- a/crates/ra_batch/src/vfs_filter.rs +++ b/crates/ra_batch/src/vfs_filter.rs | |||
@@ -1,54 +1,54 @@ | |||
1 | use std::path::PathBuf; | 1 | use std::path::PathBuf; |
2 | use ra_project_model::ProjectRoot; | 2 | use ra_project_model::ProjectRoot; |
3 | use ra_vfs::{RootEntry, Filter, RelativePath}; | 3 | use ra_vfs::{RootEntry, Filter, RelativePath}; |
4 | 4 | ||
5 | /// `IncludeRustFiles` is used to convert | 5 | /// `IncludeRustFiles` is used to convert |
6 | /// from `ProjectRoot` to `RootEntry` for VFS | 6 | /// from `ProjectRoot` to `RootEntry` for VFS |
7 | pub struct IncludeRustFiles { | 7 | pub struct IncludeRustFiles { |
8 | root: ProjectRoot, | 8 | root: ProjectRoot, |
9 | } | 9 | } |
10 | 10 | ||
11 | impl IncludeRustFiles { | 11 | impl IncludeRustFiles { |
12 | pub fn from_roots<R>(roots: R) -> impl Iterator<Item = RootEntry> | 12 | pub fn from_roots<R>(roots: R) -> impl Iterator<Item = RootEntry> |
13 | where | 13 | where |
14 | R: IntoIterator<Item = ProjectRoot>, | 14 | R: IntoIterator<Item = ProjectRoot>, |
15 | { | 15 | { |
16 | roots.into_iter().map(IncludeRustFiles::from_root) | 16 | roots.into_iter().map(IncludeRustFiles::from_root) |
17 | } | 17 | } |
18 | 18 | ||
19 | pub fn from_root(root: ProjectRoot) -> RootEntry { | 19 | pub fn from_root(root: ProjectRoot) -> RootEntry { |
20 | IncludeRustFiles::from(root).into() | 20 | IncludeRustFiles::from(root).into() |
21 | } | 21 | } |
22 | 22 | ||
23 | #[allow(unused)] | 23 | #[allow(unused)] |
24 | pub fn external(path: PathBuf) -> RootEntry { | 24 | pub fn external(path: PathBuf) -> RootEntry { |
25 | IncludeRustFiles::from_root(ProjectRoot::new(path, false)) | 25 | IncludeRustFiles::from_root(ProjectRoot::new(path, false)) |
26 | } | 26 | } |
27 | 27 | ||
28 | pub fn member(path: PathBuf) -> RootEntry { | 28 | pub fn member(path: PathBuf) -> RootEntry { |
29 | IncludeRustFiles::from_root(ProjectRoot::new(path, true)) | 29 | IncludeRustFiles::from_root(ProjectRoot::new(path, true)) |
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | impl Filter for IncludeRustFiles { | 33 | impl Filter for IncludeRustFiles { |
34 | fn include_dir(&self, dir_path: &RelativePath) -> bool { | 34 | fn include_dir(&self, dir_path: &RelativePath) -> bool { |
35 | self.root.include_dir(dir_path) | 35 | self.root.include_dir(dir_path) |
36 | } | 36 | } |
37 | 37 | ||
38 | fn include_file(&self, file_path: &RelativePath) -> bool { | 38 | fn include_file(&self, file_path: &RelativePath) -> bool { |
39 | self.root.include_file(file_path) | 39 | self.root.include_file(file_path) |
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
43 | impl std::convert::From<ProjectRoot> for IncludeRustFiles { | 43 | impl From<ProjectRoot> for IncludeRustFiles { |
44 | fn from(v: ProjectRoot) -> IncludeRustFiles { | 44 | fn from(v: ProjectRoot) -> IncludeRustFiles { |
45 | IncludeRustFiles { root: v } | 45 | IncludeRustFiles { root: v } |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | impl std::convert::From<IncludeRustFiles> for RootEntry { | 49 | impl From<IncludeRustFiles> for RootEntry { |
50 | fn from(v: IncludeRustFiles) -> RootEntry { | 50 | fn from(v: IncludeRustFiles) -> RootEntry { |
51 | let path = v.root.path().clone(); | 51 | let path = v.root.path().clone(); |
52 | RootEntry::new(path, Box::new(v)) | 52 | RootEntry::new(path, Box::new(v)) |
53 | } | 53 | } |
54 | } | 54 | } |