From 644a7bb423beaf0337f431a1152636b832e7755a Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Thu, 17 Sep 2026 20:47:50 +0000 Subject: [PATCH 1/7] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20String.isHiddenFile=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B0=9D=EC=B2=B4=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9(boxing)=20=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 3 +++ CHANGELOG.md | 2 ++ src/main/kotlin/html4tree/main.kt | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index ee124e69..1cb56143 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -62,3 +62,6 @@ ## 2026-08-11 - Array의 toMutableList 할당 오버헤드 최적화 **학습:** 배열을 정렬하기 위해 `.toMutableList()`를 호출하면 새로운 `ArrayList` 객체와 내부 배열 객체가 할당되어 대규모 디렉토리를 순회할 때 가비지 컬렉션(GC) 부하를 유발합니다. 배열 복제가 필요한 경우 `.clone()`을 사용하면 하나의 배열 객체만 새로 할당되므로 더 효율적입니다. **조치:** 디렉토리 파일 배열을 정렬하기 전에 복사할 때 `.toMutableList()` 대신 `.clone()`을 사용하여 불필요한 중간 컬렉션 할당을 제거하고 성능을 향상시켰습니다. +## 2024-03-24 - [Kotlin String.firstOrNull() Boxing Overhead] +**Learning:** Kotlin에서 문자열의 첫 글자를 확인할 때 `firstOrNull()`을 사용하면 `Char?`로 박싱(boxing)되면서 불필요한 객체 할당 오버헤드가 발생한다. 특히 파일 필터링과 같은 핫 루프(hot loop)에서는 누적된 가비지 컬렉션(GC) 부하를 유발한다. +**Action:** 성능에 민감한 핫 루프에서는 `isEmpty()` 확인 후 직접 인덱스(`this[0]`)로 접근하는 방식을 사용하여 시퀀스 구체화 및 박싱 오버헤드를 회피해야 한다. diff --git a/CHANGELOG.md b/CHANGELOG.md index c442b3b1..43a26ab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ All notable changes to this project are documented in this file. ### Changed +- 성능 향상을 위해 `String.isHiddenFile()`의 `firstOrNull()` 호출을 제거하고 직접 인덱스 접근(`this[0]`)을 사용하여 객체 할당(boxing) 오버헤드 감소 + - Improve generated directory-index readability with adjacent-row separators, explicit light and dark empty-state text colors, and text-only hover/focus underlining while retaining the full interactive target's focus outline. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 0972fa2c..8f1d3448 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -223,7 +223,8 @@ internal fun crawl_directories( } fun String.isHiddenFile(): Boolean { - return when (firstOrNull()) { + if (this.isEmpty()) return false + return when (this[0]) { '.', '\u3002', '\uFF0E', '\uFF61' -> true else -> false } From bdaf679c8f21a73f16af543762ef159b4d6719a9 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 18 Sep 2026 06:24:40 +0000 Subject: [PATCH 2/7] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20String.isHiddenFile=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B0=9D=EC=B2=B4=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9(boxing)=20=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From c1601bdaad3c824c1aabaa2b116badce6d834522 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 18 Sep 2026 17:55:01 +0000 Subject: [PATCH 3/7] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20String.isHiddenFile=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B0=9D=EC=B2=B4=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9(boxing)=20=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 8f10f5353b9a1ccd0b21292a4e01298490e38f64 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 19 Sep 2026 05:22:20 +0000 Subject: [PATCH 4/7] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20String.isHiddenFile=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B0=9D=EC=B2=B4=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9(boxing)=20=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 1b9ba8322953eeb323e64f3353e6a2d4251041ec Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 19 Sep 2026 15:10:21 +0000 Subject: [PATCH 5/7] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20String.isHiddenFile=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B0=9D=EC=B2=B4=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9(boxing)=20=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 8f23f806fd0f347845b3d9803e032c5554c85140 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 20 Sep 2026 21:41:44 +0000 Subject: [PATCH 6/7] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20String.isHiddenFile=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B0=9D=EC=B2=B4=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9(boxing)=20=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From e262ff906261a67c0c2da88532853b8b4cc73224 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Mon, 21 Sep 2026 12:28:14 +0000 Subject: [PATCH 7/7] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0]=20String.isHiddenFile=EC=9D=98=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B0=9D=EC=B2=B4=20=ED=95=A0?= =?UTF-8?q?=EB=8B=B9(boxing)=20=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit