diff options
author | Aleksey Kladov <[email protected]> | 2020-06-19 14:07:32 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-06-19 14:07:32 +0100 |
commit | b9f3c5d585ee266f0fd5db77c2a3f331a0bddf2d (patch) | |
tree | dae453e237a54c1a4e86634b71fae8890e850796 | |
parent | 902a9c6da7939abec74bb4e4be9d1d16dfb15daa (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.
-rw-r--r-- | crates/paths/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/stdx/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/vfs/src/file_set.rs | 32 | ||||
-rw-r--r-- | crates/vfs/src/lib.rs | 3 |
4 files changed, 30 insertions, 11 deletions
diff --git a/crates/paths/src/lib.rs b/crates/paths/src/lib.rs index c7ce0c42f..190c50913 100644 --- a/crates/paths/src/lib.rs +++ b/crates/paths/src/lib.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | //! relative paths. | 2 | //! relative paths. |
3 | use std::{ | 3 | use std::{ |
4 | convert::{TryFrom, TryInto}, | 4 | convert::{TryFrom, TryInto}, |
5 | ops, | 5 | io, ops, |
6 | path::{Component, Path, PathBuf}, | 6 | path::{Component, Path, PathBuf}, |
7 | }; | 7 | }; |
8 | 8 | ||
@@ -46,6 +46,9 @@ impl TryFrom<&str> for AbsPathBuf { | |||
46 | } | 46 | } |
47 | 47 | ||
48 | impl AbsPathBuf { | 48 | impl AbsPathBuf { |
49 | pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> { | ||
50 | path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap()) | ||
51 | } | ||
49 | pub fn as_path(&self) -> &AbsPath { | 52 | pub fn as_path(&self) -> &AbsPath { |
50 | AbsPath::new_unchecked(self.0.as_path()) | 53 | AbsPath::new_unchecked(self.0.as_path()) |
51 | } | 54 | } |
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index c0356344c..f2ff0e435 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs | |||
@@ -1,5 +1,4 @@ | |||
1 | //! Missing batteries for standard libraries. | 1 | //! Missing batteries for standard libraries. |
2 | |||
3 | use std::{cell::Cell, fmt, time::Instant}; | 2 | use std::{cell::Cell, fmt, time::Instant}; |
4 | 3 | ||
5 | #[inline(always)] | 4 | #[inline(always)] |
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`. |
5 | use std::{cmp, fmt, iter}; | 5 | use std::{fmt, iter}; |
6 | 6 | ||
7 | use paths::AbsPathBuf; | 7 | use paths::AbsPathBuf; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
@@ -44,6 +44,12 @@ pub struct FileSetConfig { | |||
44 | roots: Vec<(AbsPathBuf, usize)>, | 44 | roots: Vec<(AbsPathBuf, usize)>, |
45 | } | 45 | } |
46 | 46 | ||
47 | impl Default for FileSetConfig { | ||
48 | fn default() -> Self { | ||
49 | FileSetConfig::builder().build() | ||
50 | } | ||
51 | } | ||
52 | |||
47 | impl FileSetConfig { | 53 | impl 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 | ||
84 | impl FileSetConfigBuilder { | 95 | impl 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 | ||
81 | impl Vfs { | 81 | impl 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 | } |