저는 Java 8을 처음 사용합니다. 여전히 API에 대해 잘 모르지만 새로운 Streams API의 성능과 우수한 이전 컬렉션을 비교하기 위해 작은 비공식 벤치 마크를 만들었습니다.
테스트는의 목록을 필터링하고 Integer
각 짝수에 대해 제곱근을 계산하여 결과 List
로 저장합니다 Double
.
코드는 다음과 같습니다.
public static void main(String[] args) {
//Calculating square root of even numbers from 1 to N
int min = 1;
int max = 1000000;
List<Integer> sourceList = new ArrayList<>();
for (int i = min; i < max; i++) {
sourceList.add(i);
}
List<Double> result = new LinkedList<>();
//Collections approach
long t0 = System.nanoTime();
long elapsed = 0;
for (Integer i : sourceList) {
if(i % 2 == 0){
result.add(Math.sqrt(i));
}
}
elapsed = System.nanoTime() - t0;
System.out.printf("Collections: Elapsed time:\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));
//Stream approach
Stream<Integer> stream = sourceList.stream();
t0 = System.nanoTime();
result = stream.filter(i -> i%2 == 0).map(i -> Math.sqrt(i)).collect(Collectors.toList());
elapsed = System.nanoTime() - t0;
System.out.printf("Streams: Elapsed time:\t\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));
//Parallel stream approach
stream = sourceList.stream().parallel();
t0 = System.nanoTime();
result = stream.filter(i -> i%2 == 0).map(i -> Math.sqrt(i)).collect(Collectors.toList());
elapsed = System.nanoTime() - t0;
System.out.printf("Parallel streams: Elapsed time:\t %d ns \t(%f seconds)%n", elapsed, elapsed / Math.pow(10, 9));
}.
그리고 듀얼 코어 머신의 결과는 다음과 같습니다.
Collections: Elapsed time: 94338247 ns (0,094338 seconds)
Streams: Elapsed time: 201112924 ns (0,201113 seconds)
Parallel streams: Elapsed time: 357243629 ns (0,357244 seconds)
이 특정 테스트의 경우 스트림이 컬렉션보다 약 두 배 느리며 병렬 처리가 도움이되지 않습니다 (또는 내가 잘못 사용하고 있습니까?).
질문 :
- 이 시험은 공정합니까? 내가 실수 했어?
- 스트림이 컬렉션보다 느립니까? 누구든지 이것에 대한 좋은 공식 벤치 마크를 만들었습니까?
- 어떤 접근 방식을 사용해야합니까?
결과가 업데이트되었습니다.
@pveentjer의 조언에 따라 JVM 예열 (1k 반복) 후 1k 번 테스트를 실행했습니다.
Collections: Average time: 206884437,000000 ns (0,206884 seconds)
Streams: Average time: 98366725,000000 ns (0,098367 seconds)
Parallel streams: Average time: 167703705,000000 ns (0,167704 seconds)
이 경우 스트림이 더 성능이 좋습니다. 필터링 기능이 런타임 동안 한두 번만 호출되는 앱에서 무엇이 관찰 될지 궁금합니다.
toList
쓰레드가 안전하지 않은 목록을 수집하더라도 스레드를 사용하기 전에 병렬로 실행해야합니다. 다른 스레드는 병합되기 전에 스레드가 포함 된 중간 목록으로 수집하기 때문입니다.
IntStream
대신에?