Java 8 병렬처리와 성능에 대해서

자바 8의 Stream API에서 사용가능한 병렬처리 함수인 parallel를 이용할때 확인해야 할 점이 있다.

1부터 n 까지 더하는 작업을 단순 반복문 , Stream parallel 를 이용한 코드의 동작 시간을 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1. 단순 반복문
public static long iterativeSum(long n) {
long result = 0;
for (long i = 0; i <= n; i++) {
result += i;
}
return result;
}

//2. Parallel 를 이용하여 병령처리한 작업
public static long parallelSum(long n) {
return Stream.iterate(1L, i -> i + 1).limit(n).parallel().reduce(Long::sum).get();
}

//출처 Java 8 in Action

결과

1
2
3
1.  Iterative Sum done in: 3 msecs

2. Parallel forkJoinSum done in: 95 msecs

3개의 메소드를 실행 해보면 1번이 가장빠르다는것을 확인 할 수 있는데 이 예제에서 iterate 연산은 본질적으로 순차적으로 일어나기 때문에 병령처리를 해도 큰 효과를 보기 힘들고 Steam을 이용하여 계산을 할때는 기본형 데이터 타입이 아닌 참조형으로 변환하는 과정이 있기때문에 더 많은 리소스가 사용된다.

자바8을 공부하며 기존 소스를 자바8로 리펙토링 하려 했는데 무턱대고 적용하기전 확인이 필요하다.

Parallel를 이용한 코드의 성능을 높이기 위해선 기본형 long 을 직접 사용하는 “LongStream.rangeClosed“ 를 이용하면 성능을 높일수 있다.

1
2
3
public static long parallelRangedSum(long n) {
return LongStream.rangeClosed(1, n).parallel().reduce(Long::sum).getAsLong();
}

하지만 위 코드도 단순 반복문보다 빠르다고 장담 할 수는 없는데 이는 멀티코어간 데이터교환시 발생하는 비용때문이다. 코어간의 데이터 이동은 큰 작업이고 병렬처리를 할때에 코어간 데이터 교환보다 오래걸리는 작업을 병령처리로 나누어 작업하는게 효율적이다.

공유하기