From 53215ba980db5caed46b3cf145e5c601b769dddc Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Thu, 9 Jul 2026 20:57:25 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94]=20ignore=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=A0=95=EA=B7=9C=EC=8B=9D=20=EB=A7=A4=EC=B9=AD=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 디렉토리 목록을 순회하며 ignore 파일에 정의된 정규식과 매칭하는 로직을 최적화했습니다. 💡 What: - `curr_dir.list()?.sorted()` 에서 불필요한 배열 복사 및 O(N log N) 정렬 작업 제거 - 중첩된 `.forEach` 대신 `.any()`를 사용하여 매칭되는 즉시 불필요한 후속 정규식 평가를 중단(short-circuit)하도록 개선 🎯 Why: - 단순 Set에 요소를 추가하기 위해 전체 파일 목록을 정렬할 필요가 없음. - 첫 번째 매칭만으로도 제외 목록에 추가되므로 모든 규칙을 확인할 필요가 없음. 📊 Impact: - 파일 수가 많고 ignore 규칙이 많은 디렉토리의 처리 속도를 크게 개선 (O(N log N * M) -> O(N * M) 이하) 🔬 Measurement: - ./gradlew test 로 기존 동작 유지 검증 완료 - ./gradlew jacocoTestCoverageVerification 으로 100% 코드 커버리지 확인 완료 --- .jules/bolt.md | 3 +++ src/main/kotlin/html4tree/main.kt | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index a9253e7..b3605ef 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -12,3 +12,6 @@ ## 2024-07-08 - URL Encoding String Allocation Bottleneck **Learning:** `byte.toString(16).padStart(2, '0').toUpperCase()` inside a loop allocating up to 3 strings per reserved byte in a hot path causes significant GC pressure. This is a common but dangerous anti-pattern in Kotlin when processing large strings or numerous files in directory crawlers. **Action:** Replace chained string operations with direct character mapping and bitwise operations (`ushr`, `and`) when building formatted hex output, which avoids intermediate string creation entirely. Ensure 100% branch coverage with test inputs spanning both < 10 and > 9 hex values. +## 2024-08-01 - Avoid List Sorting and Re-Iteration For Matching +**Learning:** In Kotlin, using `.sorted().forEach()` and an inner `.forEach()` over regexes to find matching files is inefficient. It allocates a new list, sorts it (O(N log N)), and evaluates every regex even after a match is found. +**Action:** Remove `.sorted()` when order doesn't matter for the operation (like adding to a Set). Use `.any()` on the regex list to short-circuit evaluation as soon as the first match is found, saving CPU cycles on N * M comparisons. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index ebab59d..ffcb018 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -129,13 +129,13 @@ fun process_ignore_file(curr_dir: File): Set { } } - curr_dir.list()?.sorted()?.forEach { - val current = it - ignored_regexes.forEach { regex -> - if(regex.matches(current)){ - files_to_exclude.add(current) - } - } + // ⚡ Bolt Performance Optimization: Skip unnecessary sorting and use short-circuiting + // Removing .sorted() avoids creating a new list and sorting it when we only need to check for matches. + // Using .any() short-circuits the regex checks as soon as a match is found. + curr_dir.list()?.forEach { current -> + if (ignored_regexes.any { it.matches(current) }) { + files_to_exclude.add(current) + } } }