Skip to content

Commit b9f3c5d

Browse files
committed
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.
1 parent 902a9c6 commit b9f3c5d

File tree

4 files changed

+30
-11
lines changed

4 files changed

+30
-11
lines changed

crates/paths/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! relative paths.
33
use std::{
44
convert::{TryFrom, TryInto},
5-
ops,
5+
io, ops,
66
path::{Component, Path, PathBuf},
77
};
88

@@ -46,6 +46,9 @@ impl TryFrom<&str> for AbsPathBuf {
4646
}
4747

4848
impl AbsPathBuf {
49+
pub fn canonicalized(path: &Path) -> io::Result<AbsPathBuf> {
50+
path.canonicalize().map(|it| AbsPathBuf::try_from(it).unwrap())
51+
}
4952
pub fn as_path(&self) -> &AbsPath {
5053
AbsPath::new_unchecked(self.0.as_path())
5154
}

crates/stdx/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
//! Missing batteries for standard libraries.
2-
32
use std::{cell::Cell, fmt, time::Instant};
43

54
#[inline(always)]

crates/vfs/src/file_set.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! Files which do not belong to any explicitly configured `FileSet` belong to
44
//! the default `FileSet`.
5-
use std::{cmp, fmt, iter};
5+
use std::{fmt, iter};
66

77
use paths::AbsPathBuf;
88
use rustc_hash::FxHashMap;
@@ -44,6 +44,12 @@ pub struct FileSetConfig {
4444
roots: Vec<(AbsPathBuf, usize)>,
4545
}
4646

47+
impl Default for FileSetConfig {
48+
fn default() -> Self {
49+
FileSetConfig::builder().build()
50+
}
51+
}
52+
4753
impl FileSetConfig {
4854
pub fn builder() -> FileSetConfigBuilder {
4955
FileSetConfigBuilder::default()
@@ -60,14 +66,19 @@ impl FileSetConfig {
6066
self.n_file_sets
6167
}
6268
fn classify(&self, path: &VfsPath) -> usize {
63-
for (root, idx) in self.roots.iter() {
64-
if let Some(path) = path.as_path() {
65-
if path.starts_with(root) {
66-
return *idx;
67-
}
68-
}
69+
let path = match path.as_path() {
70+
Some(it) => it,
71+
None => return self.len() - 1,
72+
};
73+
let idx = match self.roots.binary_search_by(|(p, _)| p.as_path().cmp(path)) {
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
6981
}
70-
self.len() - 1
7182
}
7283
}
7384

@@ -82,6 +93,9 @@ impl Default for FileSetConfigBuilder {
8293
}
8394

8495
impl FileSetConfigBuilder {
96+
pub fn len(&self) -> usize {
97+
self.roots.len()
98+
}
8599
pub fn add_file_set(&mut self, roots: Vec<AbsPathBuf>) {
86100
self.roots.push(roots)
87101
}
@@ -93,7 +107,7 @@ impl FileSetConfigBuilder {
93107
.enumerate()
94108
.flat_map(|(i, paths)| paths.into_iter().zip(iter::repeat(i)))
95109
.collect();
96-
roots.sort_by_key(|(path, _)| cmp::Reverse(path.to_string_lossy().len()));
110+
roots.sort();
97111
FileSetConfig { n_file_sets, roots }
98112
}
99113
}

crates/vfs/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ pub enum ChangeKind {
7979
}
8080

8181
impl Vfs {
82+
pub fn len(&self) -> usize {
83+
self.data.len()
84+
}
8285
pub fn file_id(&self, path: &VfsPath) -> Option<FileId> {
8386
self.interner.get(path).filter(|&it| self.get(it).is_some())
8487
}

0 commit comments

Comments
 (0)