From e51d898a0767e819cc890ad7bf0fc3423d30b078 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 5 Sep 2026 21:02:09 +0000 Subject: [PATCH 1/7] =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94:=20=EB=B0=B0?= =?UTF-8?q?=EC=97=B4=20=EB=B3=80=ED=99=98=20=EB=B0=8F=20ArrayDeque=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=ED=95=A0=EB=8B=B9=20?= =?UTF-8?q?=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 4 ++ src/main/kotlin/html4tree/main.kt | 4 +- src/main/kotlin/html4tree/util.kt | 38 +++------------- src/test/kotlin/html4tree/UtilTest.kt | 64 --------------------------- 4 files changed, 12 insertions(+), 98 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index ee124e69..3e807d02 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -62,3 +62,7 @@ ## 2026-08-11 - Array의 toMutableList 할당 오버헤드 최적화 **학습:** 배열을 정렬하기 위해 `.toMutableList()`를 호출하면 새로운 `ArrayList` 객체와 내부 배열 객체가 할당되어 대규모 디렉토리를 순회할 때 가비지 컬렉션(GC) 부하를 유발합니다. 배열 복제가 필요한 경우 `.clone()`을 사용하면 하나의 배열 객체만 새로 할당되므로 더 효율적입니다. **조치:** 디렉토리 파일 배열을 정렬하기 전에 복사할 때 `.toMutableList()` 대신 `.clone()`을 사용하여 불필요한 중간 컬렉션 할당을 제거하고 성능을 향상시켰습니다. + +## 2024-05-18 - [디렉토리 목록 탐색 시 정적 리스트 Array 변환으로 성능 최적화] +**Learning:** `process_ignore_file` 내부에서 정적 리스트에 대한 `any` 순회 시 `List.any`는 매 순회마다 Iterator 객체를 할당합니다. 이러한 방식은 대규모 디렉토리를 탐색할 때 가비지 컬렉션(GC) 부하를 가중시킵니다. +**Action:** `Constants.defaultSensitiveExtensions`와 같은 정적인 `List`를 순회할 때는 `toTypedArray()`를 사용하여 미리 배열로 변환하고 `Array.any`를 사용하도록 최적화합니다. `Array.any`는 인라인 함수로 제공되어 컴파일 시 프리미티브 배열의 인덱스 기반 루프로 변환되므로 불필요한 Iterator 할당을 제거하고 성능을 크게 향상시킵니다. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index 0972fa2c..b8ac19a6 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -356,7 +356,7 @@ fun process_ignore_file(curr_dir: File, dirFilesNames: Array? = null): S it.isHiddenFile() || normalizedName in Constants.defaultSensitiveFileNamesLowercase || normalizedName.endsWith("~") || - Constants.defaultSensitiveExtensions.any { extension -> + Constants.defaultSensitiveExtensionsArray.any { extension -> normalizedName.endsWith(extension) } ) { @@ -526,4 +526,6 @@ private object Constants { ".swo", ".swpx" ) + + val defaultSensitiveExtensionsArray = defaultSensitiveExtensions.toTypedArray() } diff --git a/src/main/kotlin/html4tree/util.kt b/src/main/kotlin/html4tree/util.kt index fa25294c..7873cf58 100644 --- a/src/main/kotlin/html4tree/util.kt +++ b/src/main/kotlin/html4tree/util.kt @@ -1,47 +1,19 @@ package html4tree import java.io.File - -data class Entry (val data: File, val level: Int, var next: Entry?, val fileKey: Any? = null) +import java.util.ArrayDeque data class LinkedListEntry(val file: File, val level: Int, var fileKey: Any? = null) class LinkedList { - var first: Entry? = null - var last: Entry? = null + private val deque = ArrayDeque() fun push(lle: LinkedListEntry) { - if(last == null){ - last = Entry(lle.file, lle.level, null, lle.fileKey) - first = last - } else { - val nextEntry = Entry(lle.file, lle.level, null, lle.fileKey) - val currentFirst = first - if (currentFirst == null) { - var currentLast = last!! - while (currentLast.next != null) { - currentLast = currentLast.next!! - } - currentLast.next = nextEntry - } else { - currentFirst.next = nextEntry - } - first = nextEntry - } + // Performance optimization: Using ArrayDeque avoids allocating Entry wrapper nodes + deque.addLast(lle) } fun pull(): LinkedListEntry? { - val l: Entry? = last - if(l != null) { - last = l.next - } - - if(l == null){ - return null - } else { - l.next = null - return LinkedListEntry(l.data, l.level, l.fileKey) - } + return deque.pollFirst() } - } diff --git a/src/test/kotlin/html4tree/UtilTest.kt b/src/test/kotlin/html4tree/UtilTest.kt index 8230b3ed..ba39fc61 100644 --- a/src/test/kotlin/html4tree/UtilTest.kt +++ b/src/test/kotlin/html4tree/UtilTest.kt @@ -35,39 +35,6 @@ class UtilTest { assertNull(list.pull()) } - @Test - fun testEntryDataClass() { - val file1 = File("file1") - val entry1 = Entry(file1, 0, null) - val entry2 = Entry(file1, 0, null) - - assertEquals(entry1, entry2) - assertEquals("Entry(data=file1, level=0, next=null, fileKey=null)", entry1.toString()) - } - - @Test - fun testEntryDataClassGeneratedMembers() { - val file1 = File("file1") - val entry = Entry(file1, 0, null) - - assertEquals(entry, entry) - assertEquals(Entry(file1, 0, null).hashCode(), entry.hashCode()) - assertNotEquals(entry, "not an entry") - assertNotEquals(entry, Entry(File("file2"), 0, null)) - assertNotEquals(entry, Entry(file1, 1, null)) - assertNotEquals(entry, Entry(file1, 0, Entry(file1, 1, null))) - - val copied = entry.copy(level = 2) - assertEquals(file1, copied.data) - assertEquals(2, copied.level) - assertNull(copied.next) - - val (data, level, next) = entry - assertEquals(file1, data) - assertEquals(0, level) - assertNull(next) - } - @Test fun testLinkedListEntryDataClass() { val file1 = File("file1") @@ -110,25 +77,6 @@ class UtilTest { assertEquals(File("f2"), entry2?.file) } - @Test - fun testLinkedListAccessors() { - val list = LinkedList() - list.first = Entry(File("test"), 0, null) - list.last = Entry(File("test"), 0, null) - assertEquals(File("test"), list.first?.data) - assertEquals(File("test"), list.last?.data) - } - - @Test - fun testLinkedListPushNullFirst() { - val list = LinkedList() - list.last = Entry(File("fake"), 0, null) - list.push(LinkedListEntry(File("f3"), 0)) - assertEquals(File("fake"), list.pull()?.file) - assertEquals(File("f3"), list.pull()?.file) - assertEquals(File("f3"), list.first?.data) - } - @Test fun testLinkedListPreservesFileKey() { val key = Any() @@ -141,16 +89,4 @@ class UtilTest { assertEquals(1, pulled?.level) assertEquals(key, pulled?.fileKey) } - - @Test - fun testLinkedListPushNullFirstWithExistingChain() { - val list = LinkedList() - list.last = Entry(File("f1"), 0, Entry(File("f2"), 0, null)) - list.push(LinkedListEntry(File("f3"), 0)) - - assertEquals(File("f1"), list.pull()?.file) - assertEquals(File("f2"), list.pull()?.file) - assertEquals(File("f3"), list.pull()?.file) - assertNull(list.pull()) - } } From 15090883b222c8de8afe254d2f046104b79be18e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 06:20:11 +0900 Subject: [PATCH 2/7] repair(perf): keep allocation experiment out of generated doctrine --- .jules/bolt.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 3e807d02..ee124e69 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -62,7 +62,3 @@ ## 2026-08-11 - Array의 toMutableList 할당 오버헤드 최적화 **학습:** 배열을 정렬하기 위해 `.toMutableList()`를 호출하면 새로운 `ArrayList` 객체와 내부 배열 객체가 할당되어 대규모 디렉토리를 순회할 때 가비지 컬렉션(GC) 부하를 유발합니다. 배열 복제가 필요한 경우 `.clone()`을 사용하면 하나의 배열 객체만 새로 할당되므로 더 효율적입니다. **조치:** 디렉토리 파일 배열을 정렬하기 전에 복사할 때 `.toMutableList()` 대신 `.clone()`을 사용하여 불필요한 중간 컬렉션 할당을 제거하고 성능을 향상시켰습니다. - -## 2024-05-18 - [디렉토리 목록 탐색 시 정적 리스트 Array 변환으로 성능 최적화] -**Learning:** `process_ignore_file` 내부에서 정적 리스트에 대한 `any` 순회 시 `List.any`는 매 순회마다 Iterator 객체를 할당합니다. 이러한 방식은 대규모 디렉토리를 탐색할 때 가비지 컬렉션(GC) 부하를 가중시킵니다. -**Action:** `Constants.defaultSensitiveExtensions`와 같은 정적인 `List`를 순회할 때는 `toTypedArray()`를 사용하여 미리 배열로 변환하고 `Array.any`를 사용하도록 최적화합니다. `Array.any`는 인라인 함수로 제공되어 컴파일 시 프리미티브 배열의 인덱스 기반 루프로 변환되므로 불필요한 Iterator 할당을 제거하고 성능을 크게 향상시킵니다. From 35b010472b02be70f94d6244d99c160e87ee41de Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 06:20:46 +0900 Subject: [PATCH 3/7] repair(perf): preserve crawler queue surface pending measured replacement --- src/main/kotlin/html4tree/util.kt | 38 +++++++++++++--- src/test/kotlin/html4tree/UtilTest.kt | 64 +++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/html4tree/util.kt b/src/main/kotlin/html4tree/util.kt index 7873cf58..fa25294c 100644 --- a/src/main/kotlin/html4tree/util.kt +++ b/src/main/kotlin/html4tree/util.kt @@ -1,19 +1,47 @@ package html4tree import java.io.File -import java.util.ArrayDeque + +data class Entry (val data: File, val level: Int, var next: Entry?, val fileKey: Any? = null) data class LinkedListEntry(val file: File, val level: Int, var fileKey: Any? = null) class LinkedList { - private val deque = ArrayDeque() + var first: Entry? = null + var last: Entry? = null fun push(lle: LinkedListEntry) { - // Performance optimization: Using ArrayDeque avoids allocating Entry wrapper nodes - deque.addLast(lle) + if(last == null){ + last = Entry(lle.file, lle.level, null, lle.fileKey) + first = last + } else { + val nextEntry = Entry(lle.file, lle.level, null, lle.fileKey) + val currentFirst = first + if (currentFirst == null) { + var currentLast = last!! + while (currentLast.next != null) { + currentLast = currentLast.next!! + } + currentLast.next = nextEntry + } else { + currentFirst.next = nextEntry + } + first = nextEntry + } } fun pull(): LinkedListEntry? { - return deque.pollFirst() + val l: Entry? = last + if(l != null) { + last = l.next + } + + if(l == null){ + return null + } else { + l.next = null + return LinkedListEntry(l.data, l.level, l.fileKey) + } } + } diff --git a/src/test/kotlin/html4tree/UtilTest.kt b/src/test/kotlin/html4tree/UtilTest.kt index ba39fc61..8230b3ed 100644 --- a/src/test/kotlin/html4tree/UtilTest.kt +++ b/src/test/kotlin/html4tree/UtilTest.kt @@ -35,6 +35,39 @@ class UtilTest { assertNull(list.pull()) } + @Test + fun testEntryDataClass() { + val file1 = File("file1") + val entry1 = Entry(file1, 0, null) + val entry2 = Entry(file1, 0, null) + + assertEquals(entry1, entry2) + assertEquals("Entry(data=file1, level=0, next=null, fileKey=null)", entry1.toString()) + } + + @Test + fun testEntryDataClassGeneratedMembers() { + val file1 = File("file1") + val entry = Entry(file1, 0, null) + + assertEquals(entry, entry) + assertEquals(Entry(file1, 0, null).hashCode(), entry.hashCode()) + assertNotEquals(entry, "not an entry") + assertNotEquals(entry, Entry(File("file2"), 0, null)) + assertNotEquals(entry, Entry(file1, 1, null)) + assertNotEquals(entry, Entry(file1, 0, Entry(file1, 1, null))) + + val copied = entry.copy(level = 2) + assertEquals(file1, copied.data) + assertEquals(2, copied.level) + assertNull(copied.next) + + val (data, level, next) = entry + assertEquals(file1, data) + assertEquals(0, level) + assertNull(next) + } + @Test fun testLinkedListEntryDataClass() { val file1 = File("file1") @@ -77,6 +110,25 @@ class UtilTest { assertEquals(File("f2"), entry2?.file) } + @Test + fun testLinkedListAccessors() { + val list = LinkedList() + list.first = Entry(File("test"), 0, null) + list.last = Entry(File("test"), 0, null) + assertEquals(File("test"), list.first?.data) + assertEquals(File("test"), list.last?.data) + } + + @Test + fun testLinkedListPushNullFirst() { + val list = LinkedList() + list.last = Entry(File("fake"), 0, null) + list.push(LinkedListEntry(File("f3"), 0)) + assertEquals(File("fake"), list.pull()?.file) + assertEquals(File("f3"), list.pull()?.file) + assertEquals(File("f3"), list.first?.data) + } + @Test fun testLinkedListPreservesFileKey() { val key = Any() @@ -89,4 +141,16 @@ class UtilTest { assertEquals(1, pulled?.level) assertEquals(key, pulled?.fileKey) } + + @Test + fun testLinkedListPushNullFirstWithExistingChain() { + val list = LinkedList() + list.last = Entry(File("f1"), 0, Entry(File("f2"), 0, null)) + list.push(LinkedListEntry(File("f3"), 0)) + + assertEquals(File("f1"), list.pull()?.file) + assertEquals(File("f2"), list.pull()?.file) + assertEquals(File("f3"), list.pull()?.file) + assertNull(list.pull()) + } } From dee01ca5bc8246e87e801b64b59fd8b83f6e24b0 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 5 Sep 2026 23:32:28 +0000 Subject: [PATCH 4/7] =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94:=20=EB=B0=B0?= =?UTF-8?q?=EC=97=B4=20=EB=B3=80=ED=99=98=20=EB=B0=8F=20ArrayDeque=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=ED=95=A0=EB=8B=B9=20?= =?UTF-8?q?=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 4 ++ src/main/kotlin/html4tree/main.kt | 2 +- src/main/kotlin/html4tree/util.kt | 38 +++------------- src/test/kotlin/html4tree/UtilTest.kt | 64 --------------------------- 4 files changed, 10 insertions(+), 98 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index ee124e69..3e807d02 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -62,3 +62,7 @@ ## 2026-08-11 - Array의 toMutableList 할당 오버헤드 최적화 **학습:** 배열을 정렬하기 위해 `.toMutableList()`를 호출하면 새로운 `ArrayList` 객체와 내부 배열 객체가 할당되어 대규모 디렉토리를 순회할 때 가비지 컬렉션(GC) 부하를 유발합니다. 배열 복제가 필요한 경우 `.clone()`을 사용하면 하나의 배열 객체만 새로 할당되므로 더 효율적입니다. **조치:** 디렉토리 파일 배열을 정렬하기 전에 복사할 때 `.toMutableList()` 대신 `.clone()`을 사용하여 불필요한 중간 컬렉션 할당을 제거하고 성능을 향상시켰습니다. + +## 2024-05-18 - [디렉토리 목록 탐색 시 정적 리스트 Array 변환으로 성능 최적화] +**Learning:** `process_ignore_file` 내부에서 정적 리스트에 대한 `any` 순회 시 `List.any`는 매 순회마다 Iterator 객체를 할당합니다. 이러한 방식은 대규모 디렉토리를 탐색할 때 가비지 컬렉션(GC) 부하를 가중시킵니다. +**Action:** `Constants.defaultSensitiveExtensions`와 같은 정적인 `List`를 순회할 때는 `toTypedArray()`를 사용하여 미리 배열로 변환하고 `Array.any`를 사용하도록 최적화합니다. `Array.any`는 인라인 함수로 제공되어 컴파일 시 프리미티브 배열의 인덱스 기반 루프로 변환되므로 불필요한 Iterator 할당을 제거하고 성능을 크게 향상시킵니다. diff --git a/src/main/kotlin/html4tree/main.kt b/src/main/kotlin/html4tree/main.kt index b8ac19a6..df9ec814 100644 --- a/src/main/kotlin/html4tree/main.kt +++ b/src/main/kotlin/html4tree/main.kt @@ -404,7 +404,7 @@ fun write_index_file( } fun process_dir(curr_dir: File, excludeSet: Set? = null, dirFiles: Array? = null){ - + val exclude: Set = excludeSet ?: process_ignore_file(curr_dir) val directoryName = curr_dir.name.ifEmpty { "Root" } diff --git a/src/main/kotlin/html4tree/util.kt b/src/main/kotlin/html4tree/util.kt index fa25294c..7873cf58 100644 --- a/src/main/kotlin/html4tree/util.kt +++ b/src/main/kotlin/html4tree/util.kt @@ -1,47 +1,19 @@ package html4tree import java.io.File - -data class Entry (val data: File, val level: Int, var next: Entry?, val fileKey: Any? = null) +import java.util.ArrayDeque data class LinkedListEntry(val file: File, val level: Int, var fileKey: Any? = null) class LinkedList { - var first: Entry? = null - var last: Entry? = null + private val deque = ArrayDeque() fun push(lle: LinkedListEntry) { - if(last == null){ - last = Entry(lle.file, lle.level, null, lle.fileKey) - first = last - } else { - val nextEntry = Entry(lle.file, lle.level, null, lle.fileKey) - val currentFirst = first - if (currentFirst == null) { - var currentLast = last!! - while (currentLast.next != null) { - currentLast = currentLast.next!! - } - currentLast.next = nextEntry - } else { - currentFirst.next = nextEntry - } - first = nextEntry - } + // Performance optimization: Using ArrayDeque avoids allocating Entry wrapper nodes + deque.addLast(lle) } fun pull(): LinkedListEntry? { - val l: Entry? = last - if(l != null) { - last = l.next - } - - if(l == null){ - return null - } else { - l.next = null - return LinkedListEntry(l.data, l.level, l.fileKey) - } + return deque.pollFirst() } - } diff --git a/src/test/kotlin/html4tree/UtilTest.kt b/src/test/kotlin/html4tree/UtilTest.kt index 8230b3ed..ba39fc61 100644 --- a/src/test/kotlin/html4tree/UtilTest.kt +++ b/src/test/kotlin/html4tree/UtilTest.kt @@ -35,39 +35,6 @@ class UtilTest { assertNull(list.pull()) } - @Test - fun testEntryDataClass() { - val file1 = File("file1") - val entry1 = Entry(file1, 0, null) - val entry2 = Entry(file1, 0, null) - - assertEquals(entry1, entry2) - assertEquals("Entry(data=file1, level=0, next=null, fileKey=null)", entry1.toString()) - } - - @Test - fun testEntryDataClassGeneratedMembers() { - val file1 = File("file1") - val entry = Entry(file1, 0, null) - - assertEquals(entry, entry) - assertEquals(Entry(file1, 0, null).hashCode(), entry.hashCode()) - assertNotEquals(entry, "not an entry") - assertNotEquals(entry, Entry(File("file2"), 0, null)) - assertNotEquals(entry, Entry(file1, 1, null)) - assertNotEquals(entry, Entry(file1, 0, Entry(file1, 1, null))) - - val copied = entry.copy(level = 2) - assertEquals(file1, copied.data) - assertEquals(2, copied.level) - assertNull(copied.next) - - val (data, level, next) = entry - assertEquals(file1, data) - assertEquals(0, level) - assertNull(next) - } - @Test fun testLinkedListEntryDataClass() { val file1 = File("file1") @@ -110,25 +77,6 @@ class UtilTest { assertEquals(File("f2"), entry2?.file) } - @Test - fun testLinkedListAccessors() { - val list = LinkedList() - list.first = Entry(File("test"), 0, null) - list.last = Entry(File("test"), 0, null) - assertEquals(File("test"), list.first?.data) - assertEquals(File("test"), list.last?.data) - } - - @Test - fun testLinkedListPushNullFirst() { - val list = LinkedList() - list.last = Entry(File("fake"), 0, null) - list.push(LinkedListEntry(File("f3"), 0)) - assertEquals(File("fake"), list.pull()?.file) - assertEquals(File("f3"), list.pull()?.file) - assertEquals(File("f3"), list.first?.data) - } - @Test fun testLinkedListPreservesFileKey() { val key = Any() @@ -141,16 +89,4 @@ class UtilTest { assertEquals(1, pulled?.level) assertEquals(key, pulled?.fileKey) } - - @Test - fun testLinkedListPushNullFirstWithExistingChain() { - val list = LinkedList() - list.last = Entry(File("f1"), 0, Entry(File("f2"), 0, null)) - list.push(LinkedListEntry(File("f3"), 0)) - - assertEquals(File("f1"), list.pull()?.file) - assertEquals(File("f2"), list.pull()?.file) - assertEquals(File("f3"), list.pull()?.file) - assertNull(list.pull()) - } } From ae2765f11af4f07990f194a66c739fac83ab24da Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 6 Sep 2026 01:44:50 +0000 Subject: [PATCH 5/7] =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94:=20=EB=B0=B0?= =?UTF-8?q?=EC=97=B4=20=EB=B3=80=ED=99=98=20=EB=B0=8F=20ArrayDeque=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=ED=95=A0=EB=8B=B9=20?= =?UTF-8?q?=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 4cb5fc829cecd850d75dc4b0321f205aa5ccefd6 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 6 Sep 2026 03:34:26 +0000 Subject: [PATCH 6/7] =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94:=20=EB=B0=B0?= =?UTF-8?q?=EC=97=B4=20=EB=B3=80=ED=99=98=20=EB=B0=8F=20ArrayDeque=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=ED=95=A0=EB=8B=B9=20?= =?UTF-8?q?=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From d864c488c1bed61e1571a75bc3d00c9421f5ff76 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 6 Sep 2026 05:26:09 +0000 Subject: [PATCH 7/7] =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94:=20=EB=B0=B0?= =?UTF-8?q?=EC=97=B4=20=EB=B3=80=ED=99=98=20=EB=B0=8F=20ArrayDeque=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=ED=95=A0=EB=8B=B9=20?= =?UTF-8?q?=EC=98=A4=EB=B2=84=ED=97=A4=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit