2015-06-24 16 views
5

Ich habe einige Java8-Streams API-Codes getestet, aber ich kann nicht herausfinden, was mit diesem passiert.Java8 Streams seltsames Verhalten

Ich habe über ParallelStream nachgedacht und wie das funktioniert und ich habe einige Vergleiche angestellt. Zwei verschiedene Methoden, die eine große Iteration durchführen und 32.768.000 BigDecimals hinzufügen, eine mit ParallelStream, andere mit normaler Iteration. Ich kam mit einem Test, dass ich weiß, dass es ungültig ist, aber einige Dinge haben meine Aufmerksamkeit erregt.

Die Tests sind:

Parallel Strom:

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); 
} 

Normale Code:

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); 
} 

Ausgang ist:

Total: 536870895616000 
sumWithParallelStream(): 30502 ms 

Total: 536870895616000 
sequenceSum(): 271 ms 

Dann habe ich versucht parallelStream Entfernung:

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); 
} 

Sehen Sie, dass die sequenceSum() -Methode

Die neue Ausgabe ist die gleiche:

Total: 536870895616000 
sumWithParallelStream(): 13487 ms 

Total: 536870895616000 
sequenceSum(): 879 ms 

ich diese Änderungen vorgenommen haben, das Hinzufügen und Entfernen der parallelStream oft Methode und die Ergebnisse von sequenceSum() nie ändern, immer etwas über 200 bei der Verwendung parallelStream auf der anderen Methode, und etwas über 800 wenn nicht verwendet. Testen in Windows und Ubuntu.

Schließlich bleiben zwei Fragen für mich, warum die Verwendung von parallelStream auf die erste Methode auf die zweite beeinflusst? Warum speicherte BigDecimals auf Array die erste Methode zu langsam (800 ms zu 13000 ms)?

+1

Versuchen Sie, die Methoden in der anderen Reihenfolge aufzurufen. Zuerst 'sequenceSum()' und dann 'sumWithParallelStream()'. – Kayaman

+0

Sie machen zwei sehr unterschiedliche Dinge. Wenn Sie die parallele Methode verwenden, haben Sie eine zusätzliche Iteration über die gesamte Liste. Das dauert natürlich länger. – Nitram

+4

@Nitram Ich glaube, er fragte, warum die andere Methode die Laufzeit von 'sequenceSum()' beeinflusst. Für die ich sagen würde "JIT wahrscheinlich". – Kayaman

Antwort

0

Wie in den Kommentaren von @apangin, ist das Problem mit GC.

Ich verwendete -XX: + PrintGCDetails Parameter zum Drucken der Ausführungszeiten von GC und mit parallelStream waren sie am schlechtesten, vielleicht weil die Initialisierung der Streams API mehr Speicher zugewiesen wurde.

3

Im ersten Beispiel ordnen Sie ein Array von 32.768.000 Elementen zu und streamen dann darüber. Diese Array-Zuweisung und Speicherabruf wird nicht benötigt und ist wahrscheinlich, was die Methode verlangsamt.

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

wow ... kann nicht glauben, dass ich in Java 8 für eine Weile codiert habe und diese Funktion total vermisst habe, danke. – dolan

+0

Entschuldigung, die Antwort hier ist auf Kommentare, ich werde eine Antwort schreiben. –