diff --git a/.jules/bolt.md b/.jules/bolt.md index 39f32f6e..1f3362b9 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -1,3 +1,7 @@ ## 2024-06-21 - Regex Compilation in Loops **Learning:** In Kotlin, compiling regular expressions (`.toRegex()`) inside a loop over files is a significant O(N * M) performance bottleneck when processing ignore files (N files * M rules). **Action:** Always map string rules to compiled `Regex` objects outside of the file iteration loop (O(M) compilation) to avoid unnecessary regex re-compilations. + +## 2024-06-28 - Avoid O(n^2) operations when processing lists +**Learning:** Checking for containment (`in` / `!in`) within a `List` structure scales as O(n). When executed repeatedly inside a loop covering all `n` files of a directory listing, it inherently creates an O(n^2) operation, acting as a performance pitfall as directory sizes grow. Additionally, repeatedly concatenating strings (`+=`) in such loops leads to O(n^2) memory reallocation operations. +**Action:** When performing `n` membership queries against an exclusion list or tracking items, convert the collection to a `Set` for O(1) lookups. In Kotlin, use a `StringBuilder` or `.joinToString` rather than concatenating with `+=` within iterative structures to optimize performance. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 50b2680d..58242f39 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -54,7 +54,7 @@ fun String.urlEncodePath(): String { return java.net.URLEncoder.encode(this, "UTF-8").replace("+", "%20") } -fun process_ignore_file(curr_dir: File): List { +fun process_ignore_file(curr_dir: File): Set { val ignore_filename = ".html4ignore" @@ -62,14 +62,15 @@ fun process_ignore_file(curr_dir: File): List { val ignore_file = File(ignore_file_path) - val files_to_exclude = mutableListOf() + // BOLT OPTIMIZATION: Use mutableSetOf instead of mutableListOf for O(1) containment checks below + val files_to_exclude = mutableSetOf() if(ignore_file.exists()){ val ignored_regexes = mutableListOf() ignore_file.forEachLine { ignored_regexes.add(("^"+it+"$").toRegex()) } - curr_dir.list().sorted().forEach { + (curr_dir.list() ?: emptyArray()).forEach { val current = it ignored_regexes.forEach { regex -> if(regex.matches(current)){ @@ -87,7 +88,7 @@ fun process_ignore_file(curr_dir: File): List { fun process_dir(curr_dir: File){ - val exclude: List = process_ignore_file(curr_dir) + val exclude: Set = process_ignore_file(curr_dir) val css = """