From 6314e62cfb06ea7bbe5f530f2824010be0ffa4c7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 16 Jun 2019 19:19:38 +0300 Subject: add analysis-bench to benchmark incremental analysis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- crates/ra_batch/src/lib.rs | 42 +++++++++------ crates/ra_batch/src/vfs_filter.rs | 108 +++++++++++++++++++------------------- 2 files changed, 79 insertions(+), 71 deletions(-) (limited to 'crates/ra_batch') 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::{ CrateGraph, FileId, SourceRootId, }; use ra_ide_api::{AnalysisHost, AnalysisChange}; -use ra_project_model::ProjectWorkspace; +use ra_project_model::{ProjectWorkspace, ProjectRoot}; use ra_vfs::{Vfs, VfsChange}; use vfs_filter::IncludeRustFiles; @@ -21,13 +21,11 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId { SourceRootId(r.0) } -pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, Vec)> { +pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap)> { let root = std::env::current_dir()?.join(root); let ws = ProjectWorkspace::discover(root.as_ref())?; - let mut roots = Vec::new(); - roots.push(IncludeRustFiles::member(root.clone())); - roots.extend(IncludeRustFiles::from_roots(ws.to_roots())); - let (mut vfs, roots) = Vfs::new(roots); + let project_roots = ws.to_roots(); + let (mut vfs, roots) = Vfs::new(IncludeRustFiles::from_roots(project_roots.clone()).collect()); let crate_graph = ws.to_crate_graph(&mut |path: &Path| { let vfs_file = vfs.load(path); log::debug!("vfs file {:?} -> {:?}", path, vfs_file); @@ -35,17 +33,27 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, Vec)> { }); log::debug!("crate graph: {:?}", crate_graph); - let local_roots = roots - .into_iter() - .filter(|r| vfs.root2path(*r).starts_with(&root)) - .map(vfs_root_to_id) - .collect(); - - let host = load(root.as_path(), crate_graph, &mut vfs); - Ok((host, local_roots)) + let source_roots = roots + .iter() + .map(|&vfs_root| { + let source_root_id = vfs_root_to_id(vfs_root); + let project_root = project_roots + .iter() + .find(|it| it.path() == &vfs.root2path(vfs_root)) + .unwrap() + .clone(); + (source_root_id, project_root) + }) + .collect::>(); + let host = load(&source_roots, crate_graph, &mut vfs); + Ok((host, source_roots)) } -pub fn load(project_root: &Path, crate_graph: CrateGraph, vfs: &mut Vfs) -> AnalysisHost { +pub fn load( + source_roots: &FxHashMap, + crate_graph: CrateGraph, + vfs: &mut Vfs, +) -> AnalysisHost { let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::().ok()); let mut host = AnalysisHost::new(lru_cap); let mut analysis_change = AnalysisChange::new(); @@ -60,8 +68,8 @@ pub fn load(project_root: &Path, crate_graph: CrateGraph, vfs: &mut Vfs) -> Anal for change in vfs.commit_changes() { match change { VfsChange::AddRoot { root, files } => { - let is_local = vfs.root2path(root).starts_with(&project_root); let source_root_id = vfs_root_to_id(root); + let is_local = source_roots[&source_root_id].is_member(); log::debug!( "loaded source root {:?} with path {:?}", source_root_id, @@ -106,7 +114,7 @@ mod tests { let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); let (host, roots) = load_cargo(path).unwrap(); let mut n_crates = 0; - for root in roots { + for (root, _) in roots { for _krate in Crate::source_root_crates(host.raw_database(), root) { n_crates += 1; } 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 @@ -use std::path::PathBuf; -use ra_project_model::ProjectRoot; -use ra_vfs::{RootEntry, Filter, RelativePath}; - -/// `IncludeRustFiles` is used to convert -/// from `ProjectRoot` to `RootEntry` for VFS -pub struct IncludeRustFiles { - root: ProjectRoot, -} - -impl IncludeRustFiles { - pub fn from_roots(roots: R) -> impl Iterator - where - R: IntoIterator, - { - roots.into_iter().map(IncludeRustFiles::from_root) - } - - pub fn from_root(root: ProjectRoot) -> RootEntry { - IncludeRustFiles::from(root).into() - } - - #[allow(unused)] - pub fn external(path: PathBuf) -> RootEntry { - IncludeRustFiles::from_root(ProjectRoot::new(path, false)) - } - - pub fn member(path: PathBuf) -> RootEntry { - IncludeRustFiles::from_root(ProjectRoot::new(path, true)) - } -} - -impl Filter for IncludeRustFiles { - fn include_dir(&self, dir_path: &RelativePath) -> bool { - self.root.include_dir(dir_path) - } - - fn include_file(&self, file_path: &RelativePath) -> bool { - self.root.include_file(file_path) - } -} - -impl std::convert::From for IncludeRustFiles { - fn from(v: ProjectRoot) -> IncludeRustFiles { - IncludeRustFiles { root: v } - } -} - -impl std::convert::From for RootEntry { - fn from(v: IncludeRustFiles) -> RootEntry { - let path = v.root.path().clone(); - RootEntry::new(path, Box::new(v)) - } -} +use std::path::PathBuf; +use ra_project_model::ProjectRoot; +use ra_vfs::{RootEntry, Filter, RelativePath}; + +/// `IncludeRustFiles` is used to convert +/// from `ProjectRoot` to `RootEntry` for VFS +pub struct IncludeRustFiles { + root: ProjectRoot, +} + +impl IncludeRustFiles { + pub fn from_roots(roots: R) -> impl Iterator + where + R: IntoIterator, + { + roots.into_iter().map(IncludeRustFiles::from_root) + } + + pub fn from_root(root: ProjectRoot) -> RootEntry { + IncludeRustFiles::from(root).into() + } + + #[allow(unused)] + pub fn external(path: PathBuf) -> RootEntry { + IncludeRustFiles::from_root(ProjectRoot::new(path, false)) + } + + pub fn member(path: PathBuf) -> RootEntry { + IncludeRustFiles::from_root(ProjectRoot::new(path, true)) + } +} + +impl Filter for IncludeRustFiles { + fn include_dir(&self, dir_path: &RelativePath) -> bool { + self.root.include_dir(dir_path) + } + + fn include_file(&self, file_path: &RelativePath) -> bool { + self.root.include_file(file_path) + } +} + +impl From for IncludeRustFiles { + fn from(v: ProjectRoot) -> IncludeRustFiles { + IncludeRustFiles { root: v } + } +} + +impl From for RootEntry { + fn from(v: IncludeRustFiles) -> RootEntry { + let path = v.root.path().clone(); + RootEntry::new(path, Box::new(v)) + } +} -- cgit v1.2.3