System.arraycopy()가 빠른 이유

한봉훈·2024년 10월 9일

자바에서 배열을 복사할 때, System.arraycopy()가 빠르다는 이야기를 종종 들을 수 있다. 하지만 왜 이 메서드가 다른 방법보다 빠를까? 그 이유를 찾아가며 System.arraycopy()와 다른 방식(예: for 루프)의 실행 시간을 비교해보았다.

1. System.arraycopy()란?

System.arraycopy()는 자바에서 배열을 복사하는 대표적인 메서드이다. 이 메서드는 매우 효율적으로 배열을 복사할 수 있는데, 이는 단순한 자바 코드에서 이루어지는 것이 아니라, JVM이 내부적으로 최적화를 적용할 수 있기 때문이다.

2. System.arraycopy()의 최적화: @IntrinsicCandidate

System.arraycopy()가 빠른 이유를 찾아보던 중, 이 메서드에 @IntrinsicCandidate라는 어노테이션이 붙어 있는 것을 확인했다.

@IntrinsicCandidate는 HotSpot VM이 내부적으로 최적화할 수 있는 메서드 후보임을 나타내는 어노테이션이다. 이 어노테이션이 붙은 메서드는 JVM이 최적화된 네이티브 코드를 호출할 수 있도록 처리된다. 즉, System.arraycopy()는 자바 레벨에서 배열을 하나하나 복사하는 대신, JVM이 배열을 효율적으로 처리할 수 있도록 최적화된 방법으로 변환하는 것이다.

하지만 이 어노테이션이 붙었다고 해서 반드시 항상 최적화가 적용된다는 보장은 없다. JVM의 설정이나 실행 환경에 따라 달라질 수 있기 때문이다.

3. 직접 실행 시간 비교

이제 System.arraycopy()와 일반적인 for 루프를 사용하여 배열을 복사할 때의 실행 시간을 비교해보자. 아래는 두 방법의 성능을 비교하는 코드이다.

public class Main {
    public static void main(String[] args) {
        int[] src = new int[1000000];
        int[] dest1 = new int[1000000];
        int[] dest2 = new int[1000000];
        
        // 배열을 채우기
        for (int i = 0; i < src.length; i++) {
            src[i] = i;
        }
        
        // System.arraycopy() 사용
        long startTime1 = System.nanoTime();
        System.arraycopy(src, 0, dest1, 0, src.length);
        long endTime1 = System.nanoTime();
        System.out.println("System.arraycopy() 시간: " + (endTime1 - startTime1) + " ns");
        
        // for 루프 사용
        long startTime2 = System.nanoTime();
        for (int i = 0; i < src.length; i++) {
            dest2[i] = src[i];
        }
        long endTime2 = System.nanoTime();
        System.out.println("for 루프 시간: " + (endTime2 - startTime2) + " ns");
    }
}

코드의 실행 결과는 아래와 같다.

4. 결과 분석

실행 결과, System.arraycopy()가 일반적인 for 루프보다 훨씬 빠르게 배열을 복사하는 것을 확인할 수 있다. 그 이유는 System.arraycopy()가 JVM에서 네이티브 코드 수준으로 배열 복사 작업을 처리하기 때문이다. 반면 for 루프는 각 배열 요소를 하나씩 복사하기 때문에 자바 레벨에서 작업이 수행되며, 상대적으로 시간이 더 오래 걸린다.

5. 결론

System.arraycopy()가 빠른 이유는 @IntrinsicCandidate 어노테이션 덕분에 JVM이 내부적으로 최적화할 수 있는 메서드로 처리되기 때문이다. 이 메서드는 JVM이 배열 복사 작업을 네이티브 코드로 최적화하여 성능을 극대화할 수 있다.

성능이 중요한 배열 복사 작업에서는 System.arraycopy()를 사용하는 것이 일반적인 for 루프보다 훨씬 효율적이다. 이번 글을 통해 왜 이 메서드가 빠른지 이해하고, 실제 성능 차이를 확인할 수 있었다.

profile
백엔드 기록

0개의 댓글