You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Eliminate redundant stat calls and queue shifts in getProjectFileTree
Summary
• In common/src/project-file-tree.ts, optimize getProjectFileTree to eliminate hundreds of redundant fs.stat syscalls and replace $O(N)$ queue shifts with $O(1)$ pointer indexing.
• Previously, getProjectFileTree called parseGitignorebeforefs.readdir(fullPath) for every directory in the crawl. Because throwOnReadError was false, parseGitignore called fileExists on .gitignore, .codebuffignore, and .manicodeignore via fs.stat — performing 3 fs.stat calls on every single directory even though fs.readdir was called immediately afterwards. In addition, directories without ignore files pushed empty ignore instances onto dirIgnores, inflating the ignore chain tested on every file.
• Reordered the traversal to call fs.readdir first, and only call parseGitignore if at least one ignore file exists in the directory. Pass the directory entries to parseGitignoreWithMode so it checks the existing set rather than calling fs.stat.
• Replaced queue.shift()! with index pointer (queue[queueIndex++]) to eliminate quadratic array reallocations during large project tree crawls.
• Benchmark: In this repository, disk fs.stat calls dropped from 2,332 down to 1,726 (606 fewer fs.stat syscalls, a 26% reduction) while generating 100% identical tree output.
• Added a unit test in common/src/__tests__/project-file-tree.test.ts asserting that directories without ignore files make zero ignore-related fs.stat calls.
Test plan
[✓] bun test src/__tests__/project-file-tree.test.ts — 13 pass, 0 fail
[✓] bun run --cwd common typecheck — 0 errors in modified files
[✓] PR hygiene check passed
Nice, focused optimization. Reordering readdir before parseGitignore and reusing the already-fetched directory entries to detect the presence of .gitignore/.codebuffignore/.manicodeignore (instead of doing three separate fs.stat calls per directory) is a legitimate win, and skipping the empty-ignore-instance push for directories with no ignore files is a correctness-preserving simplification since an empty ignore() instance has no effect on filtering downstream. The queue-index pointer instead of Array.shift() is also a well-known fix for O(n) shift cost on large trees.
The new test in project-file-tree.test.ts correctly asserts zero ignore-file stat calls when none exist, which is exactly the kind of regression guard this change needs.
One edge case worth double-checking before porting: parseGitignoreWithMode now trusts directoryEntries.has(fileName) as a proxy for "file exists," but readdir entries don't distinguish files from directories. If a project ever has a directory literally named .gitignore (unlikely but possible), the old fs.stat/fileExists path likely filtered on file type, while the new path will attempt to readFile it and presumably fail into whatever catch/fallback exists. Worth a one-line comment or filter-by-isFile if the entries source ever changes to include type info (e.g., readdir(..., {withFileTypes: true})).
Overall this is a clean, in-scope, tested change - worth porting.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Eliminate redundant stat calls and queue shifts in getProjectFileTree
Summary
• In$O(N)$ queue shifts with $O(1)$ pointer indexing.
common/src/project-file-tree.ts, optimizegetProjectFileTreeto eliminate hundreds of redundantfs.statsyscalls and replace• Previously,
getProjectFileTreecalledparseGitignorebeforefs.readdir(fullPath)for every directory in the crawl. BecausethrowOnReadErrorwas false,parseGitignorecalledfileExistson.gitignore,.codebuffignore, and.manicodeignoreviafs.stat— performing 3fs.statcalls on every single directory even thoughfs.readdirwas called immediately afterwards. In addition, directories without ignore files pushed emptyignoreinstances ontodirIgnores, inflating the ignore chain tested on every file.• Reordered the traversal to call
fs.readdirfirst, and only callparseGitignoreif at least one ignore file exists in the directory. Pass the directory entries toparseGitignoreWithModeso it checks the existing set rather than callingfs.stat.• Replaced
queue.shift()!with index pointer (queue[queueIndex++]) to eliminate quadratic array reallocations during large project tree crawls.• Benchmark: In this repository, disk
fs.statcalls dropped from 2,332 down to 1,726 (606 fewerfs.statsyscalls, a 26% reduction) while generating 100% identical tree output.• Added a unit test in
common/src/__tests__/project-file-tree.test.tsasserting that directories without ignore files make zero ignore-relatedfs.statcalls.Test plan
[✓]
bun test src/__tests__/project-file-tree.test.ts— 13 pass, 0 fail[✓]
bun run --cwd common typecheck— 0 errors in modified files[✓] PR hygiene check passed