자바 마이크로벤치마크 하니스(JMH) 라이브러리를 이용해 벤치마크를 구현할 수 있습니다.
책에서는 Maven Build 도구를 사용하여 구현하였는데, 저는 Gradle Build 도구를 사용하였습니다.
딱히 어려운 점은 없었습니다.
//build.gradle 파일에서
plugins {
id 'java'
id 'me.champeau.jmh' version '0.6.6' //gradle 버전에 맞게 버전을 설정할 수 있습니다.
}
jmh {
fork = // 실행 횟수 지정
warmupIterations = // warm up 수행 횟수 지정
iterations = // 측정 횟수 지정
}
이렇게 추가해주면 설정은 끝납니다.
책에 있는 예제 코드를 실행하였습니다.
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime) // 실행하는데 걸린 평균 시간 측정
@OutputTimeUnit(TimeUnit.MILLISECONDS) // 밀리초 단위로 출력
@Fork(value = 2, jvmArgs = { "-Xms4G", "-Xmx4G" }) // 4Gb의 힙 공간을 제공한 환경에서 두 번 벤치마크를 수행해 결과의 신뢰성 확보
@Measurement(iterations = 2)
@Warmup(iterations = 3)
public class ParallelStreamBenchmark {
private static final long N = 10_000_000L;
@Benchmark // 벤치마크 대상 메서드 표시
public long iterativeSum() {
long result = 0;
for (long i = 1L; i <= N; i++) {
result += i;
}
return result;
}
@Benchmark
public long sequentialSum() {
return Stream.iterate(1L, i -> i + 1).limit(N).reduce(0L, Long::sum);
}
@Benchmark
public long parallelSum() {
return Stream.iterate(1L, i -> i + 1).limit(N).parallel().reduce(0L, Long::sum);
}
@Benchmark
public long rangedSum() {
return LongStream.rangeClosed(1, N).reduce(0L, Long::sum);
}
@Benchmark
public long parallelRangedSum() {
return LongStream.rangeClosed(1, N).parallel().reduce(0L, Long::sum);
}
@TearDown(Level.Invocation) // 매 번 벤치마크를 실행한 다음에는 가비지 컬렉터 동작 시도
public void tearDown() {
System.gc();
}
}
대망의 실행 결과입니다....
그냥 병렬로 실행한다고 좋은 성능을 발휘하는 것이 아니라 올바른 자료구조를 선택해야 병렬 실행도
최적의 성능을 발휘할 수 있다고 합니다.
( 책에서처럼 rangedSum에 병렬 스트림을 추가한 parallelRangedSum이 더 성능이 좋게 나와야 하는데, 성능이 더 않좋게 나왔네요..
원인을 찾아보겠습니다.)
자바 Gradle Build로 스트림 성능 측정하기
자바 마이크로벤치마크 하니스(JMH) 라이브러리를 이용해 벤치마크를 구현할 수 있습니다. 책에서는 Maven Build 도구를 사용하여 구현하였는데, 저는 Gradle Build 도구를 사용하였습니다. 딱히 어려운 점은 없었습니다.
이렇게 추가해주면 설정은 끝납니다.
책에 있는 예제 코드를 실행하였습니다.
대망의 실행 결과입니다....
그냥 병렬로 실행한다고 좋은 성능을 발휘하는 것이 아니라 올바른 자료구조를 선택해야 병렬 실행도 최적의 성능을 발휘할 수 있다고 합니다.
( 책에서처럼 rangedSum에 병렬 스트림을 추가한 parallelRangedSum이 더 성능이 좋게 나와야 하는데, 성능이 더 않좋게 나왔네요.. 원인을 찾아보겠습니다.)