Stream vs For-Loop 간단한 성능 비교

rivermt·2023년 8월 31일
0

JAVA

목록 보기
9/9

개요

Streamfor loop에 비해 간단한 연산을 수행하는데 더 많은 시간이 걸린다고 알려져 있다.
실제로 자바로 알고리즘 문제를 풀다가 Stream을 쓴 코드에서 TLE를 받아 고친적도 있다.

이번에도 알고리즘 문제를 풀다 문득 궁금해져서 가볍게 다뤄보려 한다.

실행 환경

우선 실행한 환경은 다음과 같다.
CPU : M2 Pro, RAM : 32GB, Java 11, IDE : InteliJ

비교 대상

비교를 해보고자 한 것은 다음과 같다.
Stream, For Loop, Primitive Type, Wrapped Type

4가지에 초점을 두고 시행해봤다.

실행

Stream With Wrapped Type

 public static void printWrappedCaseWithStream() {
        List<Integer> numbers = new ArrayList<>();
        for (int i = 0; i < 1000000; i++) {
            numbers.add(i + 1);
        }

        long startTime = System.nanoTime();
        int sum = numbers.stream()
                .mapToInt(Integer::intValue)
                .sum();
        long endTime = System.nanoTime();

        System.out.println("Sum using Stream (wrapped type): " + sum);
        System.out.println("Time taken using Stream (wrapped type): " + (endTime - startTime) + " ns\n");
    }

Stream With Primitive Type

public static void printPrimitiveCaseWithStream() {
        int[] numbers = new int[1000000];
        for (int i = 0; i < 1000000; i++) {
            numbers[i] = i + 1;
        }

        long startTime = System.nanoTime();
        int sum = Arrays.stream(numbers).sum();
        long endTime = System.nanoTime();

        System.out.println("Sum using Stream (primitive type): " + sum);
        System.out.println("Time taken using Stream (primitive type): " + (endTime - startTime) + " ns\n" );
 }

For-Loop With Wrapped Type

public static void printWrappedCaseWithForLoop() {
        List<Integer> numbers = new ArrayList<>();
        for (int i = 1; i <= 1000000; i++) {
            numbers.add(i);
        }

        long startTime = System.nanoTime();

        int sum = 0;
        for (int num : numbers) {
            sum += num;
        }
        long endTime = System.nanoTime();

        System.out.println("Sum using for loop (wrapped type): " + sum);
        System.out.println("Time taken using for loop (wrapped type): " + (endTime - startTime) + " ns");
    }

For-Loop With Primitive Type

 public static void printPrimitiveCaseWithForLoop() {
        int[] numbers = new int[1000000];
        for (int i = 0; i < 1000000; i++) {
            numbers[i] = i + 1;
        }
        long startTime = System.nanoTime();

        int sum = 0;

        for (int num : numbers) {
            sum += num;
        }
        long endTime = System.nanoTime();

        System.out.println("Sum using for loop (primitive type): " + sum);
        System.out.println("Time taken using for loop (primitive type): " + (endTime - startTime) + " ns \n");
    }

결과 정리

For LoopStream에 비해 빠르고
Primitive TypeWrapped Type 보다 빠르다.

Primitive Typestack 영역에 저장되어 JVM이 직접 참조할 수 있지만 Wrapped Type은 객체이기 때문에 heap 영역에 저장되기 때문에 간접참조 해야하고 이로인해 속도차이가 발생했다고 생각한다.

함수 내부의 로직이 복잡하여 계산 비용이 높다면StreamFor-Loop간의 성능차이가 줄어든다고 한다.

이를 통해 개발자는 항상Trade-Off를 고려하고 적절한 상황에 맞게끔 대처해야함을 느꼈다.

코테의 경우에는 대부분 효율성이 훨씬 중요하기에 Stream 사용에 지양해야겠다.

참고

관련 글을 조사하다 자세하게 비교해놓은 좋은 글을 발견해서 링크를 남긴다.

profile
화이팅!!

0개의 댓글