aboutsummaryrefslogtreecommitdiff
path: root/crates/vfs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-06-19 14:07:32 +0100
committerAleksey Kladov <[email protected]>2020-06-19 14:07:32 +0100
commitb9f3c5d585ee266f0fd5db77c2a3f331a0bddf2d (patch)
treedae453e237a54c1a4e86634b71fae8890e850796 /crates/vfs
parent902a9c6da7939abec74bb4e4be9d1d16dfb15daa (diff)
Speedup VFS::partition
The task of `partition` function is to bin the flat list of paths into disjoint filesets. Ideally, it should be incremental -- each new file should be added to a specific fileset. However, preliminary measurnments show that it is actually fast enough if we just optimize this to use a binary search instead of a linear scan.
Diffstat (limited to 'crates/vfs')
-rw-r--r--crates/vfs/src/file_set.rs32
-rw-r--r--crates/vfs/src/lib.rs3
2 files changed, 26 insertions, 9 deletions
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs
index 7dc721f7e..724606a3d 100644
--- a/crates/vfs/src/file_set.rs
+++ b/crates/vfs/src/file_set.rs
@@ -2,7 +2,7 @@
2//! 2//!
3//! Files which do not belong to any explicitly configured `FileSet` belong to 3//! Files which do not belong to any explicitly configured `FileSet` belong to
4//! the default `FileSet`. 4//! the default `FileSet`.
5use std::{cmp, fmt, iter}; 5use std::{fmt, iter};
6 6
7use paths::AbsPathBuf; 7use paths::AbsPathBuf;
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
@@ -44,6 +44,12 @@ pub struct FileSetConfig {
44 roots: Vec<(AbsPathBuf, usize)>, 44 roots: Vec<(AbsPathBuf, usize)>,
45} 45}
46 46
47impl Default for FileSetConfig {
48 fn default() -> Self {
49 FileSetConfig::builder().build()
50 }
51}
52
47impl FileSetConfig { 53impl FileSetConfig {
48 pub fn builder() -> FileSetConfigBuilder { 54 pub fn builder() -> FileSetConfigBuilder {
49 FileSetConfigBuilder::default() 55 FileSetConfigBuilder::default()
@@ -60,14 +66,19 @@ impl FileSetConfig {
60 self.n_file_sets 66 self.n_file_sets
61 } 67 }
62 fn classify(&self, path: &VfsPath) -> usize { 68 fn classify(&self, path: &VfsPath) -> usize {
63 for (root, idx) in self.roots.iter() { 69 let path = match path.as_path() {
64 if let Some(path) = path.as_path() { 70 Some(it) => it,
65 if path.starts_with(root) { 71 None => return self.len() - 1,
66 return *idx; 72 };
67 } 73 let idx = match self.roots.binary_search_by(|(p, _)| p.as_path().cmp(path)) {
68 } 74 Ok(it) => it,
75 Err(it) => it.saturating_sub(1),
76 };
77 if path.starts_with(&self.roots[idx].0) {
78 self.roots[idx].1
79 } else {
80 self.len() - 1
69 } 81 }
70 self.len() - 1
71 } 82 }
72} 83}
73 84
@@ -82,6 +93,9 @@ impl Default for FileSetConfigBuilder {
82} 93}
83 94
84impl FileSetConfigBuilder { 95impl FileSetConfigBuilder {
96 pub fn len(&self) -> usize {
97 self.roots.len()
98 }
85 pub fn add_file_set(&mut self, roots: Vec<AbsPathBuf>) { 99 pub fn add_file_set(&mut self, roots: Vec<AbsPathBuf>) {
86 self.roots.push(roots) 100 self.roots.push(roots)
87 } 101 }
@@ -93,7 +107,7 @@ impl FileSetConfigBuilder {
93 .enumerate() 107 .enumerate()
94 .flat_map(|(i, paths)| paths.into_iter().zip(iter::repeat(i))) 108 .flat_map(|(i, paths)| paths.into_iter().zip(iter::repeat(i)))
95 .collect(); 109 .collect();
96 roots.sort_by_key(|(path, _)| cmp::Reverse(path.to_string_lossy().len())); 110 roots.sort();
97 FileSetConfig { n_file_sets, roots } 111 FileSetConfig { n_file_sets, roots }
98 } 112 }
99} 113}
diff --git a/crates/vfs/src/lib.rs b/crates/vfs/src/lib.rs
index 75ce61cf9..055219b0c 100644
--- a/crates/vfs/src/lib.rs
+++ b/crates/vfs/src/lib.rs
@@ -79,6 +79,9 @@ pub enum ChangeKind {
79} 79}
80 80
81impl Vfs { 81impl Vfs {
82 pub fn len(&self) -> usize {
83 self.data.len()
84 }
82 pub fn file_id(&self, path: &VfsPath) -> Option<FileId> { 85 pub fn file_id(&self, path: &VfsPath) -> Option<FileId> {
83 self.interner.get(path).filter(|&it| self.get(it).is_some()) 86 self.interner.get(path).filter(|&it| self.get(it).is_some())
84 } 87 }