작지만 꾸준한 반복

Wrapper Class, 그렇게 느린가? (Java Autoboxing 성능 비교) 본문

공부기록/Java

Wrapper Class, 그렇게 느린가? (Java Autoboxing 성능 비교)

iamjooon2 2023. 6. 22. 18:59

우아한테크코스 방학을 맞아, 여유롭게 레벨 2 내용을 정리하고 있다.

미션 진행 중 리뷰어님께서 남겨준 AutoBoxing, AutoUnBoxing에 대해 직접 실험해보려 한다.

 

이전까지 내가 알고 있던 것은 Wrapper 클래스를 사용하면 AutoBoxing과 AutoUnBoxing을 하는 과정에서 성능 차이가 발생한다는 것이었다. 하지만 그 차이가 얼마나 유의미하게 차이나는지는 몰라, 내 두 눈으로 직접 보려고 한다!

 

GPT와의 페어프로그래밍으로 아래와 같은 코드를 뽑아냈다...!

public class AutoBoxingTest {
    public static void main(String[] args) {

        int[] primitiveArray = new int[1_000_000];
        Integer[] wrapperArray = new Integer[1_000_000];

        // int 배열 초기화
        for (int i = 0; i < primitiveArray.length; i++) {
            primitiveArray[i] = i + 1;
        }

        // Integer 배열 초기화
        for (int i = 0; i < wrapperArray.length; i++) {
            wrapperArray[i] = i + 1;
        }

        // int 배열 합산
        long startTime = System.currentTimeMillis();
        int sumPrimitive = 0;
        for (int num : primitiveArray) {
            sumPrimitive += num;
        }

        long endTime = System.currentTimeMillis();
        System.out.println("int 배열 합산 시간: " + (endTime - startTime) + "ms");

        // Integer 배열 합산
        startTime = System.currentTimeMillis();
        int sumWrapper = 0;
        for (Integer num : wrapperArray) {
            sumWrapper += num;
        }

        endTime = System.currentTimeMillis();
        System.out.println("Integer 배열 합산 시간: " + (endTime - startTime) + "ms");
    }
}

 

Integer 배열과, int 배열을 동일한 크기로 만들어준 다음 초기화 하고

향상된 for문을 이용하여, 각 내용들을 변수에 더하기까지 걸린 시간을 비교해보았다

 

대략 3배 정도 차이가 났다.

여러번 실행시켜도 실행 환경에(예 - 캐싱) 따라 다르겠지만, 근 두 배의 유의미한 차이가 났다.

 

오라클의 자바 Document에서는 AutoBoxing, AutoUnbxoing 사용 시기에 대해 아래와 같이 이야기한다

 

So when should you use autoboxing and unboxing? Use them only when there is an "impedance mismatch" between reference types and primitives, for example, when you have to put numerical values into a collection. It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code. An Integer is not a substitute for an int; autoboxing and unboxing blur the distinction between primitive types and reference types, but they do not eliminate

 

그렇다면 언제쯤 AutoBoxing과 unboxing을 사용해야 할까요? 예를 들어, 숫자 값을 집합에 넣어야 하는 경우와 같이 Reference type과 primitive type 사이에 "임피던스 불일치"가 있을 때만 사용하십시오. 과학적 컴퓨팅 또는 기타 성능에 민감한 숫자 코드에 자동 복싱 및 복싱 해제를 사용하는 것은 적절하지 않습니다. Integer는 int를 대체하는 것이 아닙니다. AutoBoxing 및 AutoUnboxing은 Reference type과 Primitive type의 구별을 모호하게 하지만 제거하지는 않습니다.

 

임피던스 불일치는, 객체와 관계형 데이터베이스가 1:1로 매핑되지 않는 것을 이야기한다

 

나의 경우는, 스프링을 쓰기 시작하고 NPE가 너무 싫어서 AutoBoxing을 해줄 수 있는 곳에서는 AutoBoxing을 전부 사용했었다.

성능상에서 내주는 점 보다, null이 떠서 서버가 종료되는 것이 더 치명적이라고 생각했기 때문이다.

 

하지만 이제 레벨 3에서는 협업을 시작할 것이다. 동료 개발자가 내가 사용한 래퍼 클래스를 보고 null 처리를 해주는 곳이 있나? 고민하는 포인트만 늘어날 수 있는 것 같다. 오히려 비즈니스 상에서 null이 발생할 이유가 없는 곳은 명시적으로 원시 타입을 사용하는 것이 더 나은 코드가 아닐까 생각한다.

 

성능상의 유의미한 차이를 느꼈으니, 앞으로 Wrapper 클래스는 RequestDTO같은 null이 생길 수 있는 곳에서만 사용하는 것으로!

 

레퍼런스: 

https://docs.oracle.com/javase/8/docs/technotes/guides/language/autoboxing.html