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 c4877e2..79462de 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -139,13 +139,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) + } } }