Saya baru mengenal Java 8. Saya masih belum tahu tentang API secara mendalam, tetapi saya telah membuat tolok ukur informal kecil untuk membandingkan kinerja API Streams baru dengan Koleksi lama yang bagus.
Tes terdiri dalam menyaring daftar Integer
, dan untuk setiap nomor bahkan, menghitung akar kuadrat dan menyimpannya dalam hasil List
dari Double
.
Ini kodenya:
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));
}.
Dan berikut adalah hasil untuk mesin dual core:
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)
Untuk pengujian khusus ini, streaming sekitar dua kali lebih lambat dari koleksi, dan paralelisme tidak membantu (atau apakah saya menggunakannya dengan cara yang salah?).
Pertanyaan:
- Apakah tes ini adil? Apakah saya melakukan kesalahan?
- Apakah streaming lebih lambat dari koleksi? Adakah yang membuat tolok ukur formal yang bagus untuk ini?
- Pendekatan mana yang harus saya perjuangkan?
Hasil yang diperbarui.
Saya menjalankan tes 1k kali setelah pemanasan JVM (iterasi 1k) seperti yang disarankan oleh @pveentjer:
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)
Dalam hal ini stream lebih performan. Saya ingin tahu apa yang akan diamati dalam aplikasi di mana fungsi penyaringan hanya dipanggil sekali atau dua kali selama runtime.
toList
harus dijalankan secara paralel bahkan jika itu kumpulkan ke daftar non-thread-safe, karena utas yang berbeda akan mengumpulkan ke daftar perantara yang dibatasi utas sebelum digabungkan.
IntStream
bukan?