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: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,6 @@
## 2026-09-01 - 대용량 문자열 서브스트링 스캐닝 루프 최적화
**Learning:** 긴 텍스트에서 여러 기준 문자열(`candidate`)을 탐색하여 다음 구역의 시작점을 찾을 때, 텍스트 전체에 대해 반복적으로 `text.find(candidate)`를 호출하면 O(N)의 비효율적인 중복 스캐닝 오버헤드가 발생합니다. 특히 가장 가까운 시작점을 찾기 위해 모든 후보를 스캔할 때 이 문제가 심화됩니다.
**Action:** 기준점(`start`)을 잡은 후, `idx = text.find(candidate, start, end)`를 사용하여 검색 범위를 동적으로 축소(`end = min(end, idx)`)하십시오. 이렇게 하면 불필요한 스캐닝 오버헤드를 막고 검색 범위를 안전하게 줄여 매우 큰 성능 향상을 얻을 수 있습니다.
## 2026-09-17 - 반복문 내 정규표현식(re.split) 사전 컴파일을 통한 성능 최적화
**Learning:** `scripts/ci/opencode_review_normalize_output.py` 내의 `runtime_assertion_is_negated` 및 `claimed_runtime_tools` 함수와 같이 빈번하게 호출되는 텍스트 처리 루프 안에서 `re.split`에 인라인 정규표현식 문자열을 사용하면 반복적으로 정규표현식이 파싱되고 캐시를 조회하는 오버헤드가 발생하여 성능이 저하된다는 것을 확인했습니다.
**Action:** 긴 텍스트를 처리하거나 빈번하게 호출되는 루프 내에서 `re.split`이나 정규표현식을 사용할 때는 모듈 수준에서 `re.compile`로 상수화하여 컴파일된 패턴 객체의 `pattern.split()` 메서드를 사용하도록 최적화해야 합니다.
8 changes: 5 additions & 3 deletions scripts/ci/opencode_review_normalize_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@
r"status=(?:passed|observed)$",
re.IGNORECASE | re.MULTILINE,
)
NEGATION_BOUNDARY_PATTERN = re.compile(r"[,;]|\bbut\b|\bhowever\b", flags=re.IGNORECASE)
ASSERTION_BOUNDARY_PATTERN = re.compile(r"[.;\n]")


def admits_missing_structural_review(reason: str, summary: str) -> bool:
Expand Down Expand Up @@ -522,7 +524,7 @@ def runtime_assertion_is_negated(
) -> bool:
"""Return whether a nearby negation applies to this execution assertion."""
prefix = text[max(0, assertion.start() - 40) : assertion.start()]
prefix = re.split(r"[,;]|\bbut\b|\bhowever\b", prefix, flags=re.IGNORECASE)[-1]
prefix = NEGATION_BOUNDARY_PATTERN.split(prefix)[-1]
return NEGATED_RUNTIME_ASSERTION_PATTERN.search(f"{prefix}{suffix}") is not None


Expand All @@ -532,8 +534,8 @@ def claimed_runtime_tools(text: str) -> tuple[str, ...]:
for tool_match in RUNTIME_TOOL_PATTERN.finditer(text):
before = text[max(0, tool_match.start() - 96) : tool_match.start()]
after = text[tool_match.end() : tool_match.end() + 96]
before = re.split(r"[.;\n]", before)[-1]
after = re.split(r"[.;\n]", after)[0]
before = ASSERTION_BOUNDARY_PATTERN.split(before)[-1]
after = ASSERTION_BOUNDARY_PATTERN.split(after)[0]
before_matches = list(RUNTIME_ASSERTION_PATTERN.finditer(before))
if before_matches:
before_match = before_matches[-1]
Expand Down
Loading