자바 8부터는 parallel 메소드만 한 번 호출하면 파이프라인을 병렬 실행할 수 있는 스트림을 지원했습니다.
동시성
프로그래밍을 할 때는 안전성(safety)
와 응답 가능(liveness)
상태를 유지해야 합니다.
책 P291의 48-1를 보면 메르센 소수를 생성하는 코드가 있습니다.
그런데 시간이 오래 걸려서 스트림 파이프라인의 parallel()
을 호출해보겠습니다.
그러면 스트림 라이브러리가 이 파이프라인을 병렬화하는 방법을 찾아내지 못하기 때문에 아무 결과도 출력하지 않습니다.
데이터 소스가 Stream.iterate거나 중간 연산으로 limit를 쓰면 파이프라인 병렬화로는 성능 개선을 기대할 수 없다.
- 파이프라인 병렬화는 limit를 다룰 때 CPU 코어가 남는다면 원소를 몇 개 더 처리한 후 제한된 개수 이후의 결과를 버려도 아무런 해가 없다고 가정합니다.
- 원소 하나를 계산하는 비용이 대략 그 이전까지의 원소 전부를 계산한 비용을 합친 것만큼 든다는 뜻입니다. (P292 아래에 설명이 나옵니다.)
- 위의 자료구조는 데이터를 원하는 크기로 정확하고 손쉽게 나눌 수 있어 다수의 스레드에 일을 분배하기 좋다는 특징이 있습니다.
참조 지역성(원소 참조들이 메모리에 연속에서 저장되어 있음)
이 뛰어납니다.- 참조 지역성이 낮으면 데이터가 주 메모리에서 캐시 메모리로 전송되어 오기를 기다리며 대부분 시간을 멍하니 보내게 됩니다.
예를들어, Stream의 reduce 연산에 건네지는 accumulator와 combiner 함수는 반드시 결합법칙을 만족
하고, 간섭 받지 않는 상태
를 갖지 않아야 합니다.
- 스트림 병렬화는 오직 성능 최적화 수단임을 기억하자.
- 스트림을 잘못 병렬화하면 오작동하게 하거나 성능을 떨어뜨린다.
- 성능 테스트를 하여 병렬화를 사용할 가치가 있는지 확인하기
- 조건이 잘 갖춰지면 parallel 메소드 호출 하나로 거의 프로세서 코어 수에 비레하는 성능 향상을 볼 수 있다.