From 13cd14b4e35b2a5a2ef32e6c8fe429d967d98181 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Mon, 10 Aug 2026 20:50:42 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=EB=94=94=EB=A0=89=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=88=9C=ED=9A=8C=20=EC=8B=9C=20=EB=AF=BC=EA=B0=90?= =?UTF-8?q?=ED=95=9C=20=ED=8C=8C=EC=9D=BC=20=EB=AA=A9=EB=A1=9D=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `process_ignore_file` 함수 내부의 `defaultSensitiveFiles` 리스트를 `private object Config`로 추출했습니다. - 빈번하게 호출되는 루프 내에서의 리스트 재할당을 방지하여 GC 오버헤드를 줄였습니다. - 100% 테스트 커버리지를 유지합니다. --- .jules/bolt.md | 3 +++ src/main/kotlin/html4tree/main.kt | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 165882d..969f261 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -46,3 +46,6 @@ ## 2025-01-24 - 단일 readAttributes 호출로 파일 속성 조회 최적화 (순회 루프) **학습:** 디렉토리 순회 루프 내에서 isDirectory 및 isSymbolicLink 두 번의 stat을 각각 호출하면 파일 시스템 I/O 오버헤드가 배가됩니다. 메모리 내 제외 규칙 확인 후 한 번의 readAttributes로 속성을 한 번에 가져오는 것이 훨씬 빠릅니다. **조치:** Files.isDirectory 및 Files.isSymbolicLink를 단일 Files.readAttributes 호출로 교체하여 O(N) I/O 통신을 최적화했습니다. +## 2025-01-24 - 불필요한 로컬 컬렉션 인스턴스화 최적화 +**Learning:** `process_ignore_file`과 같이 디렉토리마다 반복적으로 호출되는 함수 내부에서 `listOf`를 통해 리스트를 선언하면, 매 방문 시 새 컬렉션이 할당되어 불필요한 가비지 컬렉션(GC) 압력이 발생합니다. +**Action:** 자주 참조되는 정적 컬렉션은 함수 내부에 선언하지 않고 `private object`로 추출하여 애플리케이션 수명 주기 동안 한 번만 할당되도록 최적화합니다. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 8942c04..2608d32 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -95,6 +95,12 @@ li + li { private val STYLE_HASH = "sha256-" + Base64.getEncoder().encodeToString(MessageDigest.getInstance("SHA-256").digest(CSS_CONTENT.toByteArray(Charsets.UTF_8))) +// ⚡ Bolt Performance Optimization: Extract static collection to prevent redundant allocations inside the frequently called process_ignore_file loop. +private object Config { + @JvmField + val DEFAULT_SENSITIVE_FILES = listOf(".git", ".env", ".ssh", ".htpasswd", ".htaccess", "id_rsa", "id_ed25519", "secrets.yml", ".html4ignore", ".DS_Store", ".aws", ".kube", ".npmrc", ".gnupg", "config.json", "credentials.json") +} + class Html4tree : CliktCommand() { val maxLevel:Int by option(help="Number of levels deep for which to generate an index.html file", hidden = false).int().default(-1) val topDir: String by argument(help="Top directory to crawl") @@ -314,8 +320,8 @@ fun process_ignore_file(curr_dir: File, dirFilesNames: Array? = null): S files_to_exclude.add("index.html") // 보안 향상: 민감한 시스템, 설정, 시크릿 파일을 디렉토리 목록에서 기본적으로 제외하여 정보 노출(Information Exposure) 방지 - val defaultSensitiveFiles = listOf(".git", ".env", ".ssh", ".htpasswd", ".htaccess", "id_rsa", "id_ed25519", "secrets.yml", ".html4ignore", ".DS_Store", ".aws", ".kube", ".npmrc", ".gnupg", "config.json", "credentials.json") - files_to_exclude.addAll(defaultSensitiveFiles) + // ⚡ Bolt Performance Optimization: Use pre-allocated static collection instead of creating a new list on every directory visit + files_to_exclude.addAll(Config.DEFAULT_SENSITIVE_FILES) // 보안 향상: dot-like prefixes are treated as hidden to prevent visually-confusable sensitive entries from reaching generated indexes. (dirFilesNames ?: curr_dir.list())?.forEach {