Stream 은 Java 8에 추가된 Lambda를 활용할 수 있는 기술 중 하나로, 연속된 요소의 집합을 순차 처리합니다.
Stream의 병렬 처리는 데이터 병렬성을 구현한 것으로, 내부적으로는 Fork-Join Framework를 이용하며 성능을 향상할 수도 있지만 몇 가지 주의 사항이 있습니다.
- No storage 별도의 저장 공간이 필요하지 않습니다.
- Immutable 원본을 수정하지 않고 결과를 생성합니다.
- Laziness 결과를 위한 최소한의 동작만을 수행합니다.
- Possibly 무한한 값을 가질 수 있습니다.
- Consumable 스트림의 요소는 생명 주기 동안 한번만 사용됩니다.
사용하면 좋은 경우
- 충분한 개수의 가용 코어와 충분히 큰 요소당 처리 시간
- 처리 시간이 Thread Pool 과 Thread 생성의 오버헤드보다 클 때
- 비지니스 로직에 대한 충분한 이해도를 가졌을 때
- 요소의 순서에 의존하지 않는 연산
-
GOOD findAny(), allMatch(), noneMatch() BAD limit(), findFirst(), distinct() - Bad Case 이더라도 순서를 포기하는 unordered()를 통해 빠른 연산이 가능합니다.
-
- 적절한 소스
-
Good ArrayList - 랜덤 엑세스 지원
- Spliterator()를 적절히 구현할 수 있는 경우Bad LinkedList 랜덤 엑세스 미지원 HashSet, TreeSet 요소의 분리가 어려움 BufferedReader.lines() 전체 요소의 수를 알지 못함
-
주의점
- 무한 Stream 은 과도한 리소스 점유를 유발할 수 있습니다.
- 각 스레드에서 서브 데이터를 처리하고 Join 과정에서 reduce() 연산이 일어납니다.
- Primitive Type Stream을 통해 Boxing(), UnBoxing()의 낭비를 막을 수 있습니다.
- 결과의 길이를 예측할 수 없는 중간 연산이 있는 경우 적절한 Fork 가 되지 않을 수 있습니다.
Reference
- 데이터 병렬성
- 전체 데이터를 쪼개 서브 데이터들로 만들고, 각 서브 데이터들을 병렬 처리합니다.
- Fork-Join Framework
- 분할 정복 알고리즘의 형태로 서브 데이터를 만들고, 멀티 코어에 할당하여 처리합니다.
- ExecutorService 의 구현체인 ForkJoinPool을 통해 스레드를 관리합니다.
'Study' 카테고리의 다른 글
토끼책을 읽고 - 메시지를 믿을 수 있을까? (2) (0) | 2021.03.08 |
---|---|
토끼책을 읽고 - 메시지를 믿을 수 있을까? (1) (0) | 2021.03.08 |
비동기 테스트 만들기 (0) | 2021.02.25 |
Querydsl 로 가는 길 (0) | 2020.12.02 |
ParameterizedTest 를 잘해보자 (0) | 2020.08.21 |