Java 8'de yeniyim. Hala API'yi derinlemesine bilmiyorum, ancak yeni Streams API'nin performansını eski iyi Koleksiyonlarla karşılaştırmak için küçük bir gayri resmi karşılaştırma yaptım.
Test, bir listeyi filtrelemek Integer
ve her çift sayı için kare kökü hesaplamak ve bunun bir sonucu List
olarak saklamaktan oluşur Double
.
İşte kod:
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));
}.
Ve çift çekirdekli bir makinenin sonuçları:
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)
Bu özel test için, akışlar koleksiyonların yaklaşık iki katı kadar yavaştır ve paralellik yardımcı olmaz (ya da yanlış şekilde mi kullanıyorum?).
Sorular:
- Bu test adil mi? Herhangi bir hata yaptım mı?
- Akışlar koleksiyonlardan daha mı yavaş? Bu konuda iyi bir resmi kıyaslama yapan var mı?
- Hangi yaklaşım için çabalamalıyım?
Güncelleme sonuçları.
JVM ısınmasından (1k iterasyon) sonra @pveentjer tarafından tavsiye edildiği gibi testi 1k kez çalıştırdım:
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)
Bu durumda akışlar daha performanslıdır. Filtreleme işlevinin çalışma sırasında yalnızca bir veya iki kez çağrıldığı bir uygulamada ne gözlemleneceğini merak ediyorum.
toList
farklı bir iş parçacığı birleştirilmeden önce iş parçacığı olmayan ara listelerde toplanacağı için, iş parçacığı için güvenli olmayan bir listede toplasa bile paralel olarak çalışmalıdır.
IntStream
bunun yerine denedin mi?