Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
# Ignore Gradle build output directory
build

.idea
.idea
perf_test/
10 changes: 7 additions & 3 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -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-05-18 - StringBuilder over String Concatenation in Kotlin
**Learning:** In Kotlin (and Java), using `+=` for string concatenation within a loop has an O(N²) time complexity due to the immutability of `String`, which requires creating a new `String` and copying the contents on every iteration. This can become a significant bottleneck when processing large collections (like thousands of directory files).
**Action:** Always prefer using a `StringBuilder` (and ideally initializing it with an estimated capacity) for string accumulation inside loops to maintain O(N) performance and avoid unnecessary memory allocations.

## 2024-05-18 - StringBuilder over String Concatenation in Kotlin
**Learning:** In Kotlin (and Java), using `+=` for string concatenation within a loop has an O(N²) time complexity due to the immutability of `String`, which requires creating a new `String` and copying the contents on every iteration. This can become a significant bottleneck when processing large collections (like thousands of directory files).
**Action:** Always prefer using a `StringBuilder` (and ideally initializing it with an estimated capacity) for string accumulation inside loops to maintain O(N) performance and avoid unnecessary memory allocations.
12 changes: 8 additions & 4 deletions src/main/kotlin/html4tree/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,22 @@ fun process_dir(curr_dir: File){
"""

val index_middle = fun():String{
var l=""

val dir_files: MutableList<File> = curr_dir.listFiles()?.toMutableList() ?: mutableListOf()
dir_files.sortWith(compareBy ({it.name}) )

// ⚡ Bolt: 문자열 결합 성능 최적화 (O(N^2) -> O(N))
// StringBuilder를 사용하여 리스트 항목들을 하나로 합칩니다.
// dir_files의 크기를 기반으로 초기 용량을 설정하여 재할당 오버헤드를 방지합니다.
val l = StringBuilder(dir_files.size * 250)

dir_files.forEach {
val isLinkedDirectory = it.isDirectory() && !java.nio.file.Files.isSymbolicLink(it.toPath())
if((it.getName() !in exclude) && (isLinkedDirectory || !it.isDirectory())) {
l += """ <li><a style="display:block; width:100%" href="${if (isLinkedDirectory) { "./${it.getName().urlEncodePath()}/" } else { "./${it.getName().urlEncodePath()}" }}">${if (isLinkedDirectory) { "&#128193;" } else { "&rtrif;" }} ${it.getName().escapeHtml()}</a></li>"""+"\n"
l.append(""" <li><a style="display:block; width:100%" href="${if (isLinkedDirectory) { "./${it.getName().urlEncodePath()}/" } else { "./${it.getName().urlEncodePath()}" }}">${if (isLinkedDirectory) { "&#128193;" } else { "&rtrif;" }} ${it.getName().escapeHtml()}</a></li>"""+"\n")
}
}

return l;
return l.toString()
}

val index_bottom="""
Expand Down
23 changes: 23 additions & 0 deletions src/test/kotlin/html4tree/HelpTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package html4tree

import org.junit.Test
import kotlin.test.assertEquals
import java.io.ByteArrayOutputStream
import java.io.PrintStream

class HelpTest {
@Test
fun testHelp() {
val originalOut = System.out
val baos = ByteArrayOutputStream()
val ps = PrintStream(baos)
System.setOut(ps)

try {
help()
assertEquals("ERROR: help has not been written yet!\n", baos.toString().replace("\r\n", "\n"))
} finally {
System.setOut(originalOut)
}
}
}