diff --git a/.jules/bolt.md b/.jules/bolt.md index fc04ae0..1c38f9c 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -4,3 +4,6 @@ ## 2024-07-07 - R 언어에서 데이터 프레임의 특정 항목 탐색을 캐싱하여 O(N) 검색 병목 최적화 **Learning:** R에서 반복문 내부에서 특정 조건을 만족하는 데이터의 위치를 찾기 위해 `which()`를 여러 번 반복 호출하는 것은 O(N) 시간 복잡도를 가져 매번 불필요한 배열 스캔을 유발합니다. 이는 루프의 반복 횟수가 많고, 탐색해야할 데이터가 클 수록 성능 저하의 주 원인이 됩니다. **Action:** 조건에 맞는 인덱스를 최초 탐색 시 변수에 캐싱(`newIdx`, `oldIdx` 등)하여 저장하고 이후 동일한 데이터 접근 시 캐싱된 인덱스를 사용함으로써 O(1) 수준으로 성능을 향상시킬 수 있습니다. 추가로 스칼라 값에 대한 불필요한 `paste0()` 함수 호출을 제거하여 오버헤드를 줄입니다. +## 2024-07-08 - R 언어에서 루프 내 인덱스 검색(which) O(N) 병목 최적화 +**Learning:** R에서 반복문 내부에서 특정 조건을 만족하는 데이터의 위치를 찾기 위해 `which()`를 여러 번 호출하면 매번 O(N)의 선형 탐색(linear scan)이 발생하여 데이터 크기가 클수록 성능이 크게 저하됩니다. 또한 `paste0()`를 이용한 불필요한 배열 단위 문자열 생성은 반복문 오버헤드를 가중시킵니다. +**Action:** 조건에 맞는 인덱스를 최초 한 번 `split(seq_len(nrow(df)), df$column)`를 통해 리스트 형태로 캐싱(dictionary lookup)하여 루프 외부에서 O(1) 검색 체계로 만들고, 스칼라 값에 대한 불필요한 `paste0()` 함수 호출을 최적화(`paste(..., collapse=' ')`)하여 오버헤드를 줄입니다. diff --git a/R/aFIPC.R b/R/aFIPC.R index 1905c64..22552f8 100644 --- a/R/aFIPC.R +++ b/R/aFIPC.R @@ -759,6 +759,10 @@ autoFIPC <- newFormColNames <- colnames(newformXDataK[colnames(newFormModel@Data$data)]) oldFormColNames <- colnames(oldformYDataK[colnames(oldFormModel@Data$data)]) + # ⚡ Bolt: Cache parameter indices to avoid O(N) linear search inside loop + newScaleParmsItemIdxCache <- split(seq_len(nrow(NewScaleParms)), NewScaleParms$item) + oldScaleParmsItemIdxCache <- split(seq_len(nrow(OldScaleParms)), OldScaleParms$item) + for (i in seq_along(oldformCommonItemNames)) { newFormItemStr <- newformCommonItemNames[i] oldFormItemStr <- oldformCommonItemNames[i] @@ -780,34 +784,17 @@ autoFIPC <- ' as common item use' ) - newIdx <- which(NewScaleParms$item == newFormItemStr) - oldIdx <- which(OldScaleParms$item == oldFormItemStr) + # ⚡ Bolt: Use cached O(1) dictionary lookups instead of O(N) which() scans + newIdx <- newScaleParmsItemIdxCache[[newFormItemStr]] + oldIdx <- oldScaleParmsItemIdxCache[[oldFormItemStr]] - message( - ' Newform Parms: ', - paste0( - NewScaleParms[newIdx, "value"], - ' ' - ) - ) - message( - ' Oldform Parms: ', - paste0( - OldScaleParms[oldIdx, "value"], - ' ' - ) - ) + # ⚡ Bolt: Remove unnecessary paste0() array string generation overhead + message(' Newform Parms: ', paste(NewScaleParms[newIdx, "value"], collapse = ' ')) + message(' Oldform Parms: ', paste(OldScaleParms[oldIdx, "value"], collapse = ' ')) NewScaleParms[newIdx, "value"] <- OldScaleParms[oldIdx, "value"] - message( - ' Linkedform Parms: ', - paste0( - NewScaleParms[newIdx, "value"], - ' ' - ), - '\n' - ) + message(' Linkedform Parms: ', paste(NewScaleParms[newIdx, "value"], collapse = ' '), '\n') NewScaleParms[newIdx, "est"] <- FALSE