mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Refactor prefetch_project_files and VFS watch setup for improved efficiency
- Updated the `prefetch_project_files` function to perform a shallow walk of the project folder, limiting the depth to enhance performance and avoid unnecessary recursion into specific directories. - Improved the logic for handling $path roots, ensuring correct canonicalization and efficient traversal based on the relationship to the project folder. - Adjusted the VFS watch setup to watch the project folder non-recursively while allowing recursive watching for $path roots, optimizing resource usage during file monitoring. These changes enhance the accuracy and performance of file prefetching and watching in the VFS.
This commit is contained in:
parent
f53e8007ff
commit
4e9e676cf2
1 changed files with 38 additions and 16 deletions
|
|
@ -163,12 +163,14 @@ fn prefetch_project_files(project: &Project, sync_scripts_only: bool) -> io::Res
|
||||||
|
|
||||||
let mut entries: Vec<walkdir::DirEntry> = Vec::new();
|
let mut entries: Vec<walkdir::DirEntry> = Vec::new();
|
||||||
|
|
||||||
// Walk the entire project folder so that every file under it
|
// Shallow walk of project folder: just the folder entry + direct
|
||||||
// (nested project files, etc.) is covered by the is_file map.
|
// children. Covers the project file and top-level siblings (nested
|
||||||
// P1 returns NotFound for cache misses when prefetch is active.
|
// project files). One readdir syscall -- NOT recursive into
|
||||||
|
// target/, .git/, node_modules/, etc.
|
||||||
if folder.exists() {
|
if folder.exists() {
|
||||||
for e in WalkDir::new(folder)
|
for e in WalkDir::new(folder)
|
||||||
.follow_links(true)
|
.follow_links(true)
|
||||||
|
.max_depth(1)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.flatten()
|
||||||
{
|
{
|
||||||
|
|
@ -176,22 +178,29 @@ fn prefetch_project_files(project: &Project, sync_scripts_only: bool) -> io::Res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also walk $path roots that may be OUTSIDE the project folder
|
// Recursive walk of each $path root. Canonicalize to resolve ".."
|
||||||
// (e.g. $path: "../module"). These wouldn't be covered above.
|
// before the equality/starts_with checks.
|
||||||
// Canonicalize before starts_with to resolve ".." components that
|
|
||||||
// would otherwise cause false positives (e.g. project/../module
|
|
||||||
// literally starts_with project/ but is actually a sibling).
|
|
||||||
let canonical_folder = std::fs::canonicalize(folder).unwrap_or_else(|_| folder.to_path_buf());
|
let canonical_folder = std::fs::canonicalize(folder).unwrap_or_else(|_| folder.to_path_buf());
|
||||||
for root in &roots {
|
for root in &roots {
|
||||||
if !root.exists() {
|
if !root.exists() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let canonical_root = std::fs::canonicalize(root).unwrap_or_else(|_| root.to_path_buf());
|
let canonical_root = std::fs::canonicalize(root).unwrap_or_else(|_| root.to_path_buf());
|
||||||
if canonical_root.starts_with(&canonical_folder) {
|
if canonical_root == canonical_folder {
|
||||||
continue;
|
// $path points to the project folder itself -- shallow walk
|
||||||
}
|
// already covers depth 0-1, fill in the subtree.
|
||||||
for e in WalkDir::new(root).follow_links(true).into_iter().flatten() {
|
for e in WalkDir::new(root)
|
||||||
entries.push(e);
|
.follow_links(true)
|
||||||
|
.min_depth(2)
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
{
|
||||||
|
entries.push(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for e in WalkDir::new(root).follow_links(true).into_iter().flatten() {
|
||||||
|
entries.push(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,12 +355,17 @@ impl ServeSession {
|
||||||
std::thread::scope(|s| {
|
std::thread::scope(|s| {
|
||||||
s.spawn(|| {
|
s.spawn(|| {
|
||||||
let watch_start = Instant::now();
|
let watch_start = Instant::now();
|
||||||
let _ = vfs.watch(&project_folder);
|
// Watch each $path root recursively (NOT the project folder --
|
||||||
|
// that would walk target/, .git/, etc. for repo-root projects).
|
||||||
for root in &path_roots {
|
for root in &path_roots {
|
||||||
let _ = vfs.watch(root);
|
let _ = vfs.watch(root);
|
||||||
}
|
}
|
||||||
|
// Watch project folder non-recursively for project file edits.
|
||||||
|
vfs.set_watch_recursive(false);
|
||||||
|
let _ = vfs.watch(&project_folder);
|
||||||
|
vfs.set_watch_recursive(true);
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Set up {} recursive watches in {:.1?}",
|
"Set up {} watches in {:.1?}",
|
||||||
path_roots.len() + 1,
|
path_roots.len() + 1,
|
||||||
watch_start.elapsed(),
|
watch_start.elapsed(),
|
||||||
);
|
);
|
||||||
|
|
@ -396,7 +410,15 @@ impl ServeSession {
|
||||||
let ref_path_index = {
|
let ref_path_index = {
|
||||||
let mut index = crate::RefPathIndex::new();
|
let mut index = crate::RefPathIndex::new();
|
||||||
let tree_guard = tree.lock().unwrap();
|
let tree_guard = tree.lock().unwrap();
|
||||||
index.populate_from_dir(root_project.folder_location(), &tree_guard);
|
let mut ref_roots = Vec::new();
|
||||||
|
collect_path_roots(
|
||||||
|
&root_project.tree,
|
||||||
|
root_project.folder_location(),
|
||||||
|
&mut ref_roots,
|
||||||
|
);
|
||||||
|
for root in &ref_roots {
|
||||||
|
index.populate_from_dir(root, &tree_guard);
|
||||||
|
}
|
||||||
drop(tree_guard);
|
drop(tree_guard);
|
||||||
Arc::new(Mutex::new(index))
|
Arc::new(Mutex::new(index))
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue