mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 14:01:37 +00:00
Optimize syncback performance for large projects (~42% faster)
Syncback on a 132K-file project dropped from ~32s to ~18s by: - Skipping hash_tree computation in clean (non-incremental) mode, since hashes are only consulted when incremental=true (-6s) - Reusing prefetch walkdir results for orphan detection instead of walking the filesystem a second time (-1.7s) - Rewriting collect_all_paths from O(n*d) bottom-up ancestor walks to O(n) top-down BFS (-0.7s) - Adding file-size-first comparison in write_to_vfs_parallel to avoid reading files that differ in size - Scoping git ls-files --stage to project directory prefix - Adding [PERF] instrumentation at info level for every pipeline phase
This commit is contained in:
parent
338f97040c
commit
cd465a90a2
6 changed files with 425 additions and 225 deletions
33
src/git.rs
33
src/git.rs
|
|
@ -248,13 +248,25 @@ pub struct GitIndexCache {
|
|||
|
||||
impl GitIndexCache {
|
||||
pub fn new(project_root: &Path) -> Option<Self> {
|
||||
let timer = Instant::now();
|
||||
let repo_root = git_repo_root(project_root)?;
|
||||
|
||||
let output = Command::new("git")
|
||||
.args(["ls-files", "--stage"])
|
||||
.current_dir(&repo_root)
|
||||
.output()
|
||||
.ok()?;
|
||||
let project_rel_prefix = project_root
|
||||
.strip_prefix(&repo_root)
|
||||
.ok()
|
||||
.and_then(|p| p.to_str())
|
||||
.map(|s| s.replace('\\', "/"));
|
||||
|
||||
let mut cmd = Command::new("git");
|
||||
cmd.args(["ls-files", "--stage"]);
|
||||
if let Some(ref prefix) = project_rel_prefix {
|
||||
if !prefix.is_empty() {
|
||||
cmd.arg("--").arg(prefix);
|
||||
}
|
||||
}
|
||||
cmd.current_dir(&repo_root);
|
||||
|
||||
let output = cmd.output().ok()?;
|
||||
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
|
|
@ -263,7 +275,6 @@ impl GitIndexCache {
|
|||
let mut entries = HashMap::new();
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
for line in stdout.lines() {
|
||||
// Format: <mode> <sha1> <stage>\t<path>
|
||||
let (meta, path) = match line.split_once('\t') {
|
||||
Some(pair) => pair,
|
||||
None => continue,
|
||||
|
|
@ -283,10 +294,18 @@ impl GitIndexCache {
|
|||
entries.insert(project_rel, hash_hex);
|
||||
}
|
||||
|
||||
log::debug!("GitIndexCache: loaded {} index entries", entries.len());
|
||||
log::debug!(
|
||||
"GitIndexCache: loaded {} index entries in {:.3}s",
|
||||
entries.len(),
|
||||
timer.elapsed().as_secs_f64()
|
||||
);
|
||||
Some(Self { entries })
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.entries.len()
|
||||
}
|
||||
|
||||
/// Returns `true` if the new content's blob SHA1 matches the git index
|
||||
/// entry for this path, meaning the file on disk almost certainly
|
||||
/// already has this content.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue