티스토리 뷰

반응형

자바의 동시성 프로그래밍

자바는 동시성 프로그래밍을 지원하려고 항상 노력하였다.

  • 처음부터 스레드, 동기화, wait/notify를 지원
  • 자바5부터는 동시성 컬렉션인 java.util.concurrent 라이브러리와 실행자(Exeuctor) 프레임워크를 지원
  • 자바7부터는 고성능 병렬 분해 프레임워크인 포크-조인(fork-join) 패키지 추가
  • 자바8부터는 스트림의 parallel 메서드로 파이프라인을 병렬 실행할 수 있도록 지원

→ 동시성 프로그래밍을 작성하기는 점점 쉬워지고 있지만, 안전성과 응답 가능 상태를 유지하게 작성하기는 여전히 어렵다. 병렬 스트림 파이프라인 프로그래밍에서도 다름 없다.

 

스트림 병렬화

  • 스트림에서 parallel 사용시에 데이터 소스가 Stream.iterate거나 중간 연산으로 limit 를 사용하면 파이프라인 병렬화로는 성능 개선을 기대할 수 없다. 그래서 스트림 파이프라인을 잘못 병렬화하면 성능이 나빠질 뿐만 아니라 예상치 못한 동작이 발생한다.(안전 실패)
  • 스트림의 소스가 ArrayList, HashMap, HashSet, ConcurrentHashMap의 인스턴스이거나 배열, int 범위, long 범위일때 가장 병렬화의 효과가 좋음
    • 이 자료구조들은 모두 데이터를 원하는 크기로 쉽게 나눌수있어서 일을 다수의 스레드에 분배하기 좋기 때문
    • 이 자료구조들은 원소들을 순차적으로 실행할때 참조 지역성(locality of reference)이 뛰어남참조 지역성이 뛰어나다는 것은 이웃한 원소의 참조들이 메모리에 연속해서 저장되어 있다는 뜻
      연속해있지 않고 서로 떨어져 있으면 즉, 참조 지역성이 낮으면 스레드는 데이터가 주 메모리에서 캐시 메모리로 전송되어 오기를 기다리며 불필요한 시간을 보내게 된다. 참조 지역성이 가장 뛰어난 자료구조는 배열(데이터 자체가 메모리에 연속해서 저장되기 때문)
      → 참조 지역성은 많은 데이터 처리 시 병렬화할 때 아주 중요한 요소이다.

 

스트림 파이프라인의 종단 연산

스트림 파이프라인의 종단 연산의 동작 방식 또한 병렬 수행에 영향을 준다.

종단 연산 중 병렬화에 가장 적합한 것은 축소(reduction)

  • reduction은 파이프라인에서 만들어진 모든 원소를 하나로 합치는 방법
  • reduce 메서드, min, max, count, sum 같이 완성된 형태로 제공되는 메서드 중 하나를 선택해 수행
  • anyMath, allMatch, nonMatch와 같은 조건에 맞으면 바로 반환하는 메서드도 병렬화에 적합
  • 가변 축소를 수행하는 collect 메서드는 컬렉션들을 합치는 부담이 커 병렬화에 부적합

 

 

스트림 병렬화 고려사항

  • 스트림 병렬화는 오직 성능 최적화 수단임
  • 변경 전후로 성능을 테스트하여 병렬화 사용 가치가 있는지 확인해야함
  • 스트림 파이프라인을 병렬화할 일이 생각보다 적다 → 성능 효과를 보는 경우가 많지 않음
  • 그러나 조건이 잘 갖춰지면 parallel 하나로 거의 프로세서 코어 수에 비례하는 성능 향상

 

덤 값 스트림 병렬화

  • ThreadLocalRandom : 단일 쓰레드에서 사용하기 위해 만들어졌다.
  • SplittableRandom : 병렬화를 위해 설계됨 (성능이 선형으로 증가)
  • Random : 모든 연산을 동기화하기 때문에 병렬처리하면 최악

 

결론

올바른 수행과 성능 향상의 확신 없이는 스트림 파이프라인 병렬화를 사용하지 말자.

스트림을 잘못 병렬화하면 오동작이 발생하거나 성능에 악영향을 끼친다.

병렬화하는게 낫다고 생각해도 성능 테스트를 통해 변경 전후를 잘 관찰하라.

반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday