Skip to content
Open
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
@@ -1,3 +1,6 @@
## 2024-07-04 - R 언어에서 루프 내 데이터 프레임 탐색 병목 최적화
**Learning:** R에서 루프를 돌면서 매번 데이터 프레임을 서브셋팅(subsetting)하는 작업은 복사 오버헤드로 인해 매우 느려질 수 있습니다. 특히 공통 문항 수가 많아질 경우 O(N^2)의 비효율을 초래합니다.
**Action:** 루프 내에서 수행하던 데이터 프레임 조회를 루프 외부에서 한 번에 `as.character(unlist(...))`로 처리하는 벡터 연산으로 변경하여 타입 변환 없이 O(1) 수준으로 성능을 크게 향상시킬 수 있습니다.
## 2024-07-26 - R 언어에서 루프 내 불필요한 배열 스캔 및 문자열 조작 병목
**Learning:** R에서 `for` 루프 내부에서 데이터프레임의 특정 열을 조건으로 조회할 때(`which()`), 이를 루프 안에서 매번 호출하면 매번 O(N)의 스캔이 발생하여 반복 횟수에 비례해 급격한 성능 저하를 초래합니다. 또한 R 4.0 이상부터는 단일 문자열 변수를 출력할 때 `paste0()`로 감싸는 것이 불필요한 함수 호출을 유발합니다.
**Action:** 동일한 `which()` 결과를 루프 내에서 여러 번 참조해야 하는 경우 루프 내부의 변수에 캐싱(caching)하여 O(N) 연산을 1회로 줄이고, 루프 내 단일 문자열 변수의 경우 `paste0()` 래핑을 제거해 성능을 개선할 수 있습니다.
24 changes: 14 additions & 10 deletions R/aFIPC.R
Original file line number Diff line number Diff line change
Expand Up @@ -725,17 +725,21 @@ autoFIPC <-
) {
message(
'applying ',
paste0(newformCommonItemNames[i]),
newformCommonItemNames[i],
' <<< ',
paste0(oldformCommonItemNames[i]),
oldformCommonItemNames[i],
' as common item use'
)

# ⚡ Bolt: Cache index lookups to avoid repeated O(N) scans
new_idx <- which(NewScaleParms$item == newformCommonItemNames[i])
old_idx <- which(OldScaleParms$item == oldformCommonItemNames[i])

message(
' Newform Parms: ',
paste0(
NewScaleParms[
which(NewScaleParms$item == paste0(newformCommonItemNames[i])),
new_idx,
"value"
],
' '
Expand All @@ -745,26 +749,26 @@ autoFIPC <-
' Oldform Parms: ',
paste0(
OldScaleParms[
which(OldScaleParms$item == paste0(oldformCommonItemNames[i])),
old_idx,
"value"
],
' '
)
)

NewScaleParms[
which(NewScaleParms$item == paste0(newformCommonItemNames[i])),
new_idx,
"value"
] <-
OldScaleParms[
which(OldScaleParms$item == paste0(oldformCommonItemNames[i])),
old_idx,
"value"
]
message(
' Linkedform Parms: ',
paste0(
NewScaleParms[
which(NewScaleParms$item == paste0(newformCommonItemNames[i])),
new_idx,
"value"
],
' '
Expand All @@ -773,16 +777,16 @@ autoFIPC <-
)

NewScaleParms[
which(NewScaleParms$item == paste0(newformCommonItemNames[i])),
new_idx,
"est"
] <-
FALSE
} else {
message(
'skipping ',
paste0(newformCommonItemNames[i]),
newformCommonItemNames[i],
' <<< ',
paste0(oldformCommonItemNames[i]),
oldformCommonItemNames[i],
' as common item use'
)
}
Expand Down
Loading