Java

Java8의 for, stream foreach, parallelStream foreach 간단 속도 테스트

체리필터 2017. 2. 14. 11:28
728x90
반응형

Java8에 들어간 stream, parallelStream이 좋다는 이야기만 듣고 대충 개념만 이해한 상태에서...
"그냥 좋겠지"란생각으로 쓰려다...

간단하게 테스트 해보고 정리 ^^ 참고로 로컬 PC에서 돌렸으며, 로컬 PC의 물리 cpu 코어 개수는 4개이다.

import java.util.ArrayList;
import java.util.List;

public class StreamTest {

	public static void main(String[] args) throws InterruptedException {
		List<Integer> intList = new ArrayList<>();
		
		// 테스트할 loop의 개수...
		for (int i = 0; i<1000000; i++) {
			intList.add(i);
		}
		
		// normal for loop
		long startTime = System.currentTimeMillis();
		for (Integer integer : intList) {
			if(integer % 1000 == 0) {
				System.out.println(integer);
				//Thread.sleep(10);
			}
		}
		long endTime = System.currentTimeMillis();
		
		// stream foreach
		long startTime2 = System.currentTimeMillis();		
		intList.stream().forEach(integer -> {
			if(integer % 1000 == 0) {
				System.out.println(integer);
				try {
					//Thread.sleep(10);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		long endTime2 = System.currentTimeMillis();
		
		// parallelStream foreach
		long startTime3 = System.currentTimeMillis();		
		intList.parallelStream().forEach(integer -> {
			if(integer % 1000 == 0) {
				System.out.println(integer);
				try {
					//Thread.sleep(10);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
		long endTime3 = System.currentTimeMillis();		
		
		System.out.println("##  1 소요시간(초.0f) : " + ( endTime - startTime )/1000.00f +"초");
		System.out.println("##  2 소요시간(초.0f) : " + ( endTime2 - startTime2 )/1000.00f +"초");
		System.out.println("##  3 소요시간(초.0f) : " + ( endTime3 - startTime3 )/1000.00f +"초");
	}
}

 

 


10만건, 100만건 테스트를 그냥 간단하게 2, 3회 정도 실시해 본 결과는 아래와 같다.

 

10만

##  1 소요시간(초.0f) : 0.005초

##  2 소요시간(초.0f) : 0.058초

##  3 소요시간(초.0f) : 0.013초

 

##  1 소요시간(초.0f) : 0.004초

##  2 소요시간(초.0f) : 0.042초

##  3 소요시간(초.0f) : 0.007초

 

100만

##  1 소요시간(초.0f) : 0.015초

##  2 소요시간(초.0f) : 0.063초

##  3 소요시간(초.0f) : 0.056초

 

##  1 소요시간(초.0f) : 0.015초

##  2 소요시간(초.0f) : 0.062초

##  3 소요시간(초.0f) : 0.058초

 

결과 1이 단순 for loop, 결과 2가 stream, 결과 3이 parallelStream 이다.

10만건이 되었든 100만건이 되었든... 단순 for loop가 빠르다.

이로 인해 내릴 수 있는 결론은 loop문 안에서 처리되는 비즈니스 로직에 block이나 delay 요소가 없다면 단순 for loop로 돌리는게 더 빠를 수 있다. stream이나 parallelStream은 list를 stream으로 바꾸고 내부적으로 라이브러리를 사용하는 비용이 소모 되므로 단순 작업에서는 더 느릴 수 있다고 어디선가 본 것 같다 ^^;;

 

그럼 loop문 안에 인위적으로 sleep을 넣는다면? 소스 코드 안의 sleep을 주석을 풀고 실행하게 되면 결과는 아래와 같다.

 

10만

##  1 소요시간(초.0f) : 1.001초

##  2 소요시간(초.0f) : 1.037초

##  3 소요시간(초.0f) : 0.144초

 

##  1 소요시간(초.0f) : 1.0초

##  2 소요시간(초.0f) : 1.077초

##  3 소요시간(초.0f) : 0.161초

 

100만

##  1 소요시간(초.0f) : 10.012초

##  2 소요시간(초.0f) : 10.09초

##  3 소요시간(초.0f) : 1.289초

 

##  1 소요시간(초.0f) : 10.004초

##  2 소요시간(초.0f) : 10.105초

##  3 소요시간(초.0f) : 1.291초

 

단순 for loop와 stream은 거의 차이가 없으며 parallelStream이 압도적으로 빠르다.

list를 parallelStream 으로 변환하고 라이브러리를 로드하고 사용하는 비용을 쓰더라도 loop문 안에서 지연이 발생해서 loop를 도는 속도가 현저히 떨어지게 된다면 병렬로 나눠 처리하는 것이 좋다는 결론을 얻게 된다.

 

하지만 loop 안에서 지연이 발생한다고 해서 무조건 parallelStream 을 쓰는 것이 좋을까?

경험 상 병렬로 작업을 처리한다 하더라도 loop 내부에 DB Insert, Update, Delete와 같은 것이 있다면 DB에 크나큰 부담으로 시스템 장애를 일으킬 수 있으니 조심해야 한다.

또한 parallelStream 이 CPU를 점유할 경우 다른 parallelStream 작업에도 영향을 미칠 수 있으므로 조심 ^^

 

덧. for loop보다 stream이 이론 상으로 더 빨라야 하는 것 같은데... 오히려 stream이 느리네..

stream이 더 빠른 경우가 무엇인지에 대한 고민이 필요 ^^;;

 

 

728x90
반응형