From 80ed94a8c3cb3c3a5ba4e82c3e2510b62895f31e Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 5 Jun 2026 05:30:32 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=88=9C=ED=9A=8C=20=EC=84=B1?= =?UTF-8?q?=EB=8A=A5=20=EC=B5=9C=EC=A0=81=ED=99=94=20(readdirSync)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit src/files.ts의 walkFiles 함수에서 디렉토리 순회 시 발생하는 I/O 병목을 해결했습니다. 기존에는 readdirSync로 파일 이름만 가져온 후 statSync를 추가로 호출하여 디렉토리 여부를 확인했으나, withFileTypes 옵션을 사용하여 추가적인 I/O 없이 fs.Dirent 객체에서 바로 확인할 수 있도록 최적화했습니다. --- .jules/bolt.md | 3 +++ src/files.ts | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..5ec706f --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-06-05 - Avoid statSync in filesystem traversal +**Learning:** In local-first CLI applications that heavily rely on file system traversal, using `readdirSync` followed by `statSync` creates a severe performance bottleneck due to excessive I/O operations. +**Action:** Always use `readdirSync(path, { withFileTypes: true })` to retrieve `fs.Dirent` objects which provide `.isDirectory()` without additional I/O overhead. diff --git a/src/files.ts b/src/files.ts index b1e1e43..a499108 100644 --- a/src/files.ts +++ b/src/files.ts @@ -1,4 +1,4 @@ -import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"; +import { existsSync, readdirSync, readFileSync } from "node:fs"; import { basename, dirname, join, relative, resolve } from "node:path"; export type VspecConfig = { vspec_format: 1; key_prefix: string; spec_language?: "ko" | "en" | "match-input" }; @@ -27,10 +27,11 @@ 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)); + // ⚡ Bolt: Use withFileTypes to avoid separate statSync calls, which significantly reduces I/O overhead + // when traversing large directories. + 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); } return files.sort();