From 2c5e9912383c545c72f7d3734db5394b2b55416a Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Thu, 3 Sep 2026 21:40:03 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=EB=94=95=EC=85=94?= =?UTF-8?q?=EB=84=88=EB=A6=AC=20=EC=88=9C=ED=9A=8C=20=EC=8B=9C=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=A1=B0=ED=9A=8C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 4 ++++ src/newsdom_api/dom_builder.py | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 1d2f017a..167af60a 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -63,3 +63,7 @@ ## 2024-07-30 - Avoid chained string replace when checking character sets **Learning:** Using chained `.replace(a, "").replace(b, "")` to check if a string consists entirely of specific characters requires intermediate string allocations for every call. In benchmarks, using `.strip("ab")` is ~30% faster and avoids multiple allocations in the hot path. **Action:** When checking if a string is solely composed of specific characters, use `.strip(chars)` instead of chained `.replace()` calls to improve performance. + +## 2024-08-10 - 딕셔너리 순회 시 items()를 사용하여 중복 조회(Lookup) 제거 +**Learning:** 성능이 중요한 반복문 내에서 딕셔너리의 키를 순회하며 `dict.get(key)` 또는 `dict[key]`로 값을 다시 조회하는 것은 불필요한 해시맵 조회를 발생시킵니다. 딕셔너리의 키는 고유하므로, `sorted(dict.items())`를 사용하면 추가 조회 없이도 키-값 쌍에 바로 접근할 수 있으며 기존의 키 정렬과 동일한 순서를 유지합니다. +**Action:** 딕셔너리를 순회하며 키와 값을 모두 사용해야 할 때는, 루프 내부에서 조회하는 대신 `for key, value in dict.items():` 또는 `sorted(dict.items())`를 사용하여 불필요한 해시맵 조회를 제거합니다. diff --git a/src/newsdom_api/dom_builder.py b/src/newsdom_api/dom_builder.py index 74778b2a..8729fed6 100644 --- a/src/newsdom_api/dom_builder.py +++ b/src/newsdom_api/dom_builder.py @@ -386,8 +386,9 @@ def _build_pages_without_page_idx( "Some blocks are missing page_idx; content was assigned to page_idx 0 while preserving model-declared page count." ) pages = [] - for page_idx in sorted(page_info_by_idx): - page_info = page_info_by_idx.get(page_idx, {}) + # ⚡ Bolt: Use sorted(dict.items()) to avoid redundant O(1) hash map lookups inside the hot loop. + # Since dict keys are strictly unique, tuple comparison short-circuits and preserves the exact sorting order. + for page_idx, page_info in sorted(page_info_by_idx.items()): pages.append( _build_page_dom( content_list if page_idx == 0 else [], @@ -425,11 +426,13 @@ def _build_pages_with_page_idx( pages = [] article_seq = count(1) - for page_idx in sorted(blocks_by_page_idx): + # ⚡ Bolt: Use sorted(dict.items()) to avoid redundant O(1) hash map lookups inside the hot loop. + # Since dict keys are strictly unique, tuple comparison short-circuits and preserves the exact sorting order. + for page_idx, blocks in sorted(blocks_by_page_idx.items()): page_info = page_info_by_idx.get(page_idx, {}) pages.append( _build_page_dom( - blocks_by_page_idx[page_idx], + blocks, page_number=_page_number_from_info(page_info, page_idx + 1), article_seq=article_seq, width=page_info.get("width"), From 2472815e1d9a7d96aeedbbe0bbcd229f8eee0d43 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 17:17:59 +0900 Subject: [PATCH 2/3] docs(perf): restore repository-owned Bolt guidance --- .jules/bolt.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 167af60a..1d2f017a 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -63,7 +63,3 @@ ## 2024-07-30 - Avoid chained string replace when checking character sets **Learning:** Using chained `.replace(a, "").replace(b, "")` to check if a string consists entirely of specific characters requires intermediate string allocations for every call. In benchmarks, using `.strip("ab")` is ~30% faster and avoids multiple allocations in the hot path. **Action:** When checking if a string is solely composed of specific characters, use `.strip(chars)` instead of chained `.replace()` calls to improve performance. - -## 2024-08-10 - 딕셔너리 순회 시 items()를 사용하여 중복 조회(Lookup) 제거 -**Learning:** 성능이 중요한 반복문 내에서 딕셔너리의 키를 순회하며 `dict.get(key)` 또는 `dict[key]`로 값을 다시 조회하는 것은 불필요한 해시맵 조회를 발생시킵니다. 딕셔너리의 키는 고유하므로, `sorted(dict.items())`를 사용하면 추가 조회 없이도 키-값 쌍에 바로 접근할 수 있으며 기존의 키 정렬과 동일한 순서를 유지합니다. -**Action:** 딕셔너리를 순회하며 키와 값을 모두 사용해야 할 때는, 루프 내부에서 조회하는 대신 `for key, value in dict.items():` 또는 `sorted(dict.items())`를 사용하여 불필요한 해시맵 조회를 제거합니다. From 847ee4fbba0e65b19cde23db8c4903e3ceef446a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 17:59:52 +0900 Subject: [PATCH 3/3] perf(dom): retire unverified page-map micro-optimization --- src/newsdom_api/dom_builder.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/newsdom_api/dom_builder.py b/src/newsdom_api/dom_builder.py index 8729fed6..74778b2a 100644 --- a/src/newsdom_api/dom_builder.py +++ b/src/newsdom_api/dom_builder.py @@ -386,9 +386,8 @@ def _build_pages_without_page_idx( "Some blocks are missing page_idx; content was assigned to page_idx 0 while preserving model-declared page count." ) pages = [] - # ⚡ Bolt: Use sorted(dict.items()) to avoid redundant O(1) hash map lookups inside the hot loop. - # Since dict keys are strictly unique, tuple comparison short-circuits and preserves the exact sorting order. - for page_idx, page_info in sorted(page_info_by_idx.items()): + for page_idx in sorted(page_info_by_idx): + page_info = page_info_by_idx.get(page_idx, {}) pages.append( _build_page_dom( content_list if page_idx == 0 else [], @@ -426,13 +425,11 @@ def _build_pages_with_page_idx( pages = [] article_seq = count(1) - # ⚡ Bolt: Use sorted(dict.items()) to avoid redundant O(1) hash map lookups inside the hot loop. - # Since dict keys are strictly unique, tuple comparison short-circuits and preserves the exact sorting order. - for page_idx, blocks in sorted(blocks_by_page_idx.items()): + for page_idx in sorted(blocks_by_page_idx): page_info = page_info_by_idx.get(page_idx, {}) pages.append( _build_page_dom( - blocks, + blocks_by_page_idx[page_idx], page_number=_page_number_from_info(page_info, page_idx + 1), article_seq=article_seq, width=page_info.get("width"),