-
Notifications
You must be signed in to change notification settings - Fork 0
⚡ Bolt: [성능 개선] walkFiles 디렉토리 순회 I/O 병목 최적화 #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| ## 2024-05-18 - fs.readdirSync performance bottleneck | ||
| **Learning:** Found a severe performance bottleneck in `walkFiles` which combines `fs.readdirSync` with `fs.statSync`. This forces synchronous I/O blocks for every file/directory just to determine if it's a directory. | ||
| **Action:** Replace `fs.readdirSync(..., { withFileTypes: true })` which returns `Dirent` objects, avoiding the need for individual `statSync` calls to check `isDirectory()`. This improves I/O performance significantly when traversing large file trees in this CLI app. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -27,10 +27,9 @@ export function projectKey(start = process.cwd()): string | null { | |||||||||||||||||||||
| export function walkFiles(root: string, predicate: (path: string) => boolean): string[] { | ||||||||||||||||||||||
| if (!existsSync(root)) return []; | ||||||||||||||||||||||
| const files: string[] = []; | ||||||||||||||||||||||
| for (const entry of readdirSync(root)) { | ||||||||||||||||||||||
| const path = join(root, entry); | ||||||||||||||||||||||
| const stat = statSync(path); | ||||||||||||||||||||||
| if (stat.isDirectory()) files.push(...walkFiles(path, predicate)); | ||||||||||||||||||||||
| for (const entry of readdirSync(root, { withFileTypes: true })) { | ||||||||||||||||||||||
| const path = join(root, entry.name); | ||||||||||||||||||||||
| if (entry.isDirectory()) files.push(...walkFiles(path, predicate)); | ||||||||||||||||||||||
| else if (predicate(path)) files.push(path); | ||||||||||||||||||||||
|
Comment on lines
+30
to
33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 심볼릭 링크 디렉토리 순회 누락 회귀가 발생합니다. Line 32에서 수정 제안 (성능 이점 유지 + 링크 디렉토리만 폴백 stat) for (const entry of readdirSync(root, { withFileTypes: true })) {
const path = join(root, entry.name);
- if (entry.isDirectory()) files.push(...walkFiles(path, predicate));
+ const isDir = entry.isDirectory() || (entry.isSymbolicLink() && statSync(path).isDirectory());
+ if (isDir) files.push(...walkFiles(path, predicate));
else if (predicate(path)) files.push(path);
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| } | ||||||||||||||||||||||
| return files.sort(); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
학습 기록 날짜가 현재 PR 시점과 불일치합니다.
Line 1의
2024-05-18은 이번 변경(PR 생성일: 2026-06-08)과 맞지 않아 추적성을 떨어뜨립니다. 실제 기록 시점으로 맞춰 주세요.🤖 Prompt for AI Agents