2015-06-24 26 views
5

Tôi đã thử nghiệm một số mã API dòng Java8, nhưng tôi không thể tìm ra điều đang xảy ra với mã này.Dòng Java8 hành vi lạ

Tôi đã suy nghĩ về ParallelStream và cách thức này hoạt động và tôi đã thực hiện một số so sánh. Hai phương pháp khác nhau thực hiện một phép lặp lớn thêm 32.768.000 BigDecimals, một phương thức sử dụng ParallelStream, một phương thức khác sử dụng lặp lại bình thường. Tôi đến với một bài kiểm tra mà tôi biết nó không hợp lệ, nhưng một số thứ gọi là sự chú ý của tôi.

Các thử nghiệm bao gồm:

Parallel dòng:

private static void sumWithParallelStream() { 
    BigDecimal[] list = new BigDecimal[32_768_000]; 
    BigDecimal total = BigDecimal.ZERO; 
    for (int i = 0; i < 32_768_000; i++) { 
     list[i] = new BigDecimal(i); 
    } 
    total = Arrays.asList(list).parallelStream().reduce(BigDecimal.ZERO, BigDecimal::add); 
    System.out.println("Total: " + total); 
} 

đang bình thường:

private static void sequenceSum() { 
    BigDecimal total = BigDecimal.ZERO; 
    for (int i = 0; i < 32_768_000; i++) { 
     total = total.add(new BigDecimal(i)); 
    } 
    System.out.println("Total: " + total); 
} 

Output là:

Total: 536870895616000 
sumWithParallelStream(): 30502 ms 

Total: 536870895616000 
sequenceSum(): 271 ms 

Sau đó, tôi đã cố gắng loại bỏ parallelStream:

private static void sumWithParallelStream() { 
    BigDecimal[] list = new BigDecimal[32_768_000]; 
    BigDecimal total = BigDecimal.ZERO; 
    for (int i = 0; i < 32_768_000; i++) { 
     list[i] = new BigDecimal(i); 
     total = total.add(list[i]); 
    } 
    System.out.println("Total: " + total); 
} 

Xem rằng phương pháp sequenceSum() là như nhau

Sản lượng mới:

Total: 536870895616000 
sumWithParallelStream(): 13487 ms 

Total: 536870895616000 
sequenceSum(): 879 ms 

tôi đã thực hiện những thay đổi này, thêm và loại bỏ các parallelStream phương pháp nhiều lần và kết quả của sequenceSum() không bao giờ thay đổi, luôn luôn có một cái gì đó về 200 khi sử dụng parallelStream trên phương pháp khác, và một cái gì đó về 800 khi không sử dụng. Thử nghiệm trong Windows và Ubuntu.

Cuối cùng, hai câu hỏi vẫn còn cho tôi, tại sao việc sử dụng parallelStream trên phương pháp đầu tiên ảnh hưởng đến phương pháp thứ hai? Tại sao lưu trữ BigDecimals trên mảng làm phương pháp đầu tiên quá chậm (800 ms đến 13000 ms)?

+1

Thử gọi các phương thức theo thứ tự khác. Đầu tiên 'sequenceSum()' và sau đó 'sumWithParallelStream()'. – Kayaman

+0

Bạn làm hai việc rất khác nhau. Khi bạn sử dụng phương pháp song song, bạn có thêm một lần lặp trên toàn bộ danh sách. Tất nhiên mất nhiều thời gian hơn. – Nitram

+4

@Nitram Tôi tin rằng anh ta hỏi tại sao phương pháp khác ảnh hưởng đến thời gian chạy của 'sequenceSum()'. Tôi muốn nói "JIT có lẽ". – Kayaman

Trả lời

0

Như đã nêu trong nhận xét của @apangin, vấn đề là với GC.

Tôi đã sử dụng -XX: + Thông số PrintGCDetails để in thời gian thực thi của GC và với parallelStream chúng là tồi tệ nhất, có thể do việc cấp thêm bộ nhớ API luồng được cấp phát.

3

Trong ví dụ đầu tiên, bạn phân bổ một mảng 32.768.000 phần tử, sau đó phát trực tiếp trên đó. Việc phân bổ mảng và tìm nạp bộ nhớ không cần thiết và có lẽ điều này làm chậm phương thức.

IntStream.range(0, limit).parallel() 
    .mapToObj(BigDecimal::new) 
    .reduce(BigDecimal.ZERO, BigDecimal::add); 
+0

wow ... không thể tin rằng tôi đã được mã hóa trong java 8 trong một thời gian và hoàn toàn bị mất chức năng đó, cảm ơn. – dolan

+0

Xin lỗi, câu trả lời ở đây là về nhận xét, tôi sẽ viết câu trả lời. –