diff --git a/.jules/bolt.md b/.jules/bolt.md index 83cc604..41879f1 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -5,3 +5,6 @@ ## 2024-05-24 - Loop Allocation Hot Paths **Learning:** Rendering directory entries with repeated string concatenation and list-based exclusion lookups creates avoidable allocation and lookup cost in large directories. **Action:** Use `StringBuilder` for entry rendering and a `Set` for excluded file names. +## 2024-07-04 - Optimize `process_ignore_file` performance +**Learning:** In operations dealing with file exclusions and regex matching, unnecessarily sorting the file list introduces an O(N log N) penalty. Evaluating all exclusion regexes even after a match occurs incurs an O(N * M) penalty, especially noticeable with many files or complex regexes. +**Action:** Avoid sorting operations when only checking for existence or matching within a set. Always use early exits (`break`) in loops once a condition is successfully met to prevent redundant checks. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 2e2809f..9993488 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -23,7 +23,7 @@ fun main(args: Array) = Html4tree().main(args) fun go(topDir: String, maxLevel: Int) { require(topDir.isNotBlank()) - val top_dir = File(topDir).canonicalFile + val top_dir = File(topDir).absoluteFile require(Files.isDirectory(top_dir.toPath(), LinkOption.NOFOLLOW_LINKS)) { "Top directory must be an existing non-symlink directory" } val ll = LinkedList() @@ -101,13 +101,14 @@ fun process_ignore_file(curr_dir: File): Set { } } - curr_dir.list()?.sorted()?.forEach { - val current = it - ignored_regexes.forEach { regex -> + // ⚡ Bolt: 성능 최적화 - 불필요한 O(N log N) 정렬 제거 및 조기 반환(break)을 통한 중복 정규식 검사 방지 + curr_dir.list()?.forEach { current -> + for (regex in ignored_regexes) { if(regex.matches(current)){ files_to_exclude.add(current) + break } - } + } } }