From 6dfeb4ad85328fd97b18959cfd2c17fef7a143bf Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Mon, 6 Jul 2026 16:13:11 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20R/aFIPC.R=EC=9D=98=20for?= =?UTF-8?q?=EB=A3=A8=ED=94=84=20=EB=82=B4=20O(N)=20=EC=8A=A4=EC=BA=94=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=ED=98=B8=EC=B6=9C=20=EB=B0=8F=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20paste0=20=EC=B5=9C=EC=A0=81?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 3 +++ R/aFIPC.R | 24 ++++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 1abb238..5af3dd7 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -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()` 래핑을 제거해 성능을 개선할 수 있습니다. diff --git a/R/aFIPC.R b/R/aFIPC.R index 2e5ac4a..a61c40e 100644 --- a/R/aFIPC.R +++ b/R/aFIPC.R @@ -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" ], ' ' @@ -745,7 +749,7 @@ autoFIPC <- ' Oldform Parms: ', paste0( OldScaleParms[ - which(OldScaleParms$item == paste0(oldformCommonItemNames[i])), + old_idx, "value" ], ' ' @@ -753,18 +757,18 @@ autoFIPC <- ) 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" ], ' ' @@ -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' ) }