From 605d71cd07521695832844be2f5f8722f52d8653 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Tue, 8 Sep 2026 16:02:00 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=ED=94=84=EB=A0=88=EC=9E=84=20=EB=B3=80=ED=99=98(as?= =?UTF-8?q?.data.frame)=20=EC=83=9D=EB=9E=B5=EC=9C=BC=EB=A1=9C=20O(N)=20?= =?UTF-8?q?=EB=A9=94=EB=AA=A8=EB=A6=AC=20=ED=95=A0=EB=8B=B9=20=EB=B0=A9?= =?UTF-8?q?=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit R에서 열 개수를 세기 위해 행렬을 `as.data.frame()`으로 변환하면 불필요한 O(N) 메모리 할당과 복사 오버헤드가 발생합니다. `ncol()`은 행렬을 기본적으로 지원하므로, 성능 향상을 위해 대상 객체에 직접 호출해야 합니다. --- .jules/bolt.md | 5 +++++ R/aFIPC.R | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 7d3c603f..b562de42 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -16,3 +16,8 @@ ## 2025-02-12 - R 언어에서 반복적인 mirt 모델 생성 시 불필요한 데이터프레임 부분집합 추출 최적화 **Learning:** R에서 데이터프레임의 특정 열을 추출하는 작업(`df[cols]`)은 O(N)의 메모리 복사를 수반합니다. `autoFIPC`에서 `mirt` 모델의 파라미터를 설정하거나 호출하는 과정 중에 `newformXDataK[colnames(newFormModel@Data$data)]` 코드가 반복해서 사용되었고, 심지어 `ncol()`을 위해 단순히 개수를 구할 때도 사용되어 불필요한 메모리 할당과 오버헤드를 초래했습니다. **Action:** 조건문이나 반복문 내부에서 불필요하게 데이터프레임 부분집합 연산이 반복되지 않도록 외부에서 한 번만 `linkedFormData <- newformXDataK[colnames(newFormModel@Data$data)]`로 캐싱(caching)한 뒤, `ncol(linkedFormData)`와 `data = linkedFormData` 형태로 재사용하여 메모리 복사와 O(N) 오버헤드를 방지해야 합니다. +## 2024-09-08 - 데이터 프레임 변환을 생략하여 O(N) 메모리 할당 방지 + +**Learning:** R에서 열 개수를 세기 위해 행렬을 `as.data.frame()`으로 변환하면 불필요한 O(N) 메모리 할당과 복사 오버헤드가 발생합니다. `ncol()`은 행렬을 기본적으로 지원하므로, 성능 향상을 위해 대상 객체에 직접 호출해야 합니다. + +**Action:** 행렬이나 데이터 프레임의 열 개수를 셀 때, 절대 `as.data.frame()`으로 먼저 변환하지 마십시오. 객체에 직접 `ncol()`을 사용하십시오. diff --git a/R/aFIPC.R b/R/aFIPC.R index 62546519..b7abff3c 100644 --- a/R/aFIPC.R +++ b/R/aFIPC.R @@ -86,8 +86,8 @@ autoFIPC <- if (!is.character(itemtype)) stop('Security Error: itemtype must be a character vector') nItems <- NA_integer_ - if (is.data.frame(newformXData) || is.matrix(newformXData)) nItems <- ncol(as.data.frame(newformXData)) - else if (is.data.frame(oldformYData) || is.matrix(oldformYData)) nItems <- ncol(as.data.frame(oldformYData)) + if (is.data.frame(newformXData) || is.matrix(newformXData)) nItems <- ncol(newformXData) # ⚡ Bolt: Avoid O(N) memory allocation by skipping as.data.frame() + else if (is.data.frame(oldformYData) || is.matrix(oldformYData)) nItems <- ncol(oldformYData) # ⚡ Bolt: Avoid O(N) memory allocation by skipping as.data.frame() if (!is.na(nItems) && !(length(itemtype) == 1 || length(itemtype) == nItems)) stop(sprintf('Security Error: itemtype must be length 1 or length %d (number of items).', nItems)) # boolean parameter validation From 46d2568b9eda94641e70ad98777c88546dc1f12e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 9 Sep 2026 01:21:40 +0900 Subject: [PATCH 2/2] revert(perf): withdraw unmeasured ncol allocation optimization --- .jules/bolt.md | 5 ----- R/aFIPC.R | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index b562de42..7d3c603f 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -16,8 +16,3 @@ ## 2025-02-12 - R 언어에서 반복적인 mirt 모델 생성 시 불필요한 데이터프레임 부분집합 추출 최적화 **Learning:** R에서 데이터프레임의 특정 열을 추출하는 작업(`df[cols]`)은 O(N)의 메모리 복사를 수반합니다. `autoFIPC`에서 `mirt` 모델의 파라미터를 설정하거나 호출하는 과정 중에 `newformXDataK[colnames(newFormModel@Data$data)]` 코드가 반복해서 사용되었고, 심지어 `ncol()`을 위해 단순히 개수를 구할 때도 사용되어 불필요한 메모리 할당과 오버헤드를 초래했습니다. **Action:** 조건문이나 반복문 내부에서 불필요하게 데이터프레임 부분집합 연산이 반복되지 않도록 외부에서 한 번만 `linkedFormData <- newformXDataK[colnames(newFormModel@Data$data)]`로 캐싱(caching)한 뒤, `ncol(linkedFormData)`와 `data = linkedFormData` 형태로 재사용하여 메모리 복사와 O(N) 오버헤드를 방지해야 합니다. -## 2024-09-08 - 데이터 프레임 변환을 생략하여 O(N) 메모리 할당 방지 - -**Learning:** R에서 열 개수를 세기 위해 행렬을 `as.data.frame()`으로 변환하면 불필요한 O(N) 메모리 할당과 복사 오버헤드가 발생합니다. `ncol()`은 행렬을 기본적으로 지원하므로, 성능 향상을 위해 대상 객체에 직접 호출해야 합니다. - -**Action:** 행렬이나 데이터 프레임의 열 개수를 셀 때, 절대 `as.data.frame()`으로 먼저 변환하지 마십시오. 객체에 직접 `ncol()`을 사용하십시오. diff --git a/R/aFIPC.R b/R/aFIPC.R index b7abff3c..62546519 100644 --- a/R/aFIPC.R +++ b/R/aFIPC.R @@ -86,8 +86,8 @@ autoFIPC <- if (!is.character(itemtype)) stop('Security Error: itemtype must be a character vector') nItems <- NA_integer_ - if (is.data.frame(newformXData) || is.matrix(newformXData)) nItems <- ncol(newformXData) # ⚡ Bolt: Avoid O(N) memory allocation by skipping as.data.frame() - else if (is.data.frame(oldformYData) || is.matrix(oldformYData)) nItems <- ncol(oldformYData) # ⚡ Bolt: Avoid O(N) memory allocation by skipping as.data.frame() + if (is.data.frame(newformXData) || is.matrix(newformXData)) nItems <- ncol(as.data.frame(newformXData)) + else if (is.data.frame(oldformYData) || is.matrix(oldformYData)) nItems <- ncol(as.data.frame(oldformYData)) if (!is.na(nItems) && !(length(itemtype) == 1 || length(itemtype) == nItems)) stop(sprintf('Security Error: itemtype must be length 1 or length %d (number of items).', nItems)) # boolean parameter validation