Java-Stream-Operation Fusion und Stateful Zwischenoperationen

8

Ich habe versucht zu verstehen und zu zeigen, wie Java-Streams eine Art von Loop-Fusion unter der Haube implementieren, so dass mehrere Operationen zu einem einzigen Durchgang verschmolzen werden können.

Dieses erste Beispiel hier:

%Vor%

Hat die folgende Ausgabe (mit der Fusion eines einzelnen Durchlaufs für jedes Element ziemlich klar):

%Vor%

Das zweite Beispiel ist dasselbe, aber ich verwende die sorted () Operation zwischen dem Filter und der Map:

%Vor%

Dies hat die folgende Ausgabe:

%Vor%

Also meine Frage ist hier, mit dem Aufruf zu distinct, bin ich richtig in der Annahme, dass es, weil es eine "stateful" Zwischenoperation ist, es nicht erlaubt, einzelne Elemente während eines einzigen Durchgangs (von allen Operationen) einzeln zu verarbeiten . Da die sortierte () statusbehaftete Operation den gesamten Eingabestrom verarbeiten muss, um ein Ergebnis zu erzeugen, kann die Verschmelzungstechnik hier nicht eingesetzt werden, weshalb die gesamte Filterung zuerst erfolgt und dann die Zuordnungs- und Druckoperationen zusammengeführt werden Nach der Sorte? Bitte korrigieren Sie mich, wenn eine meiner Annahmen falsch ist, und fühlen Sie sich frei, das zu erläutern, was ich bereits gesagt habe.

Wie entscheidet es darüber hinaus unter der Haube, ob es Elemente zu einem einzigen Durchgang fusionieren kann oder nicht, zum Beispiel, wenn die distinct () Operation existiert, gibt es einfach ein Flag, das ausschaltet, um zu verhindern, dass es passiert wie es tut, wenn distinct () nicht da ist?

Eine letzte Abfrage ist, während der Vorteil der Fusing-Operationen in einem einzigen Durchgang manchmal offensichtlich ist, zum Beispiel in Kombination mit einem Kurzschluss. Was sind die Hauptvorteile der Fusion von Operationen wie einer Filter-Map-for-Each oder sogar einer Filter-Map-Summe?

    
Tranquility 28.01.2016, 18:19
quelle

2 Antworten

11

Die Consumer -Objekten und gießen die Daten hinein. Jedes Element kann unabhängig voneinander betrieben werden, so dass niemals etwas in der Kette "stecken bleibt". (Das ist es, was Louis mit der Implementierung von Fusion meint - wir stellen die Stufen zu einer großen Funktion zusammen und füttern die Daten dazu.)

Stateful -Operationen (distinct, sorted, limit usw.) sind komplizierter und variieren in ihrem Verhalten. Jede zustandsorientierte Operation wählt selbst, wie sie sich implementieren will, und kann so den am wenigsten aufdringlichen Ansatz wählen. Zum Beispiel, distinct (unter bestimmten Umständen), lassen Elemente herauskommen, während sie überprüft werden, während sorted eine volle Barriere darstellt. (Der Unterschied besteht darin, wie viel Faulheit möglich ist und wie gut sie Dinge wie unendliche Quellen mit einer Grenzoperation stromabwärts behandeln.)

Es ist richtig, dass Stateful-Operationen im Allgemeinen einige der Vorteile der Fusion unterminieren, aber nicht alle (die Upstream- und Downstream-Operationen können noch fusioniert werden).

Zusätzlich zum Wert des Kurzschlusses, den Sie beobachtet haben, sind zusätzliche große Gewinne aus der Fusion: (a) Sie müssen keine Zwischenergebniscontainer zwischen den Stufen füllen und (b) die Daten, mit denen Sie es zu tun haben immer "heiß" im Cache.

    
Brian Goetz 28.01.2016, 20:00
quelle
4

Ja, das ist in Ordnung. All dies kann durch einen Blick auf den Quellcode überprüft werden.

Fusion wird nicht so implementiert, wie ich denke, dass Sie es für richtig halten. Es gibt keinen Blick auf die gesamte Pipeline und entscheiden, wie es zu fusionieren; Es gibt keine Flaggen oder irgendetwas; Es ist nur, ob die Operationen als ein StatefulOp -Objekt ausgedrückt werden, das den gesamten Stream bis zu diesem Punkt ausführen und die gesamte Ausgabe erhalten kann, oder eine StatelessOp , die nur eine Sink schmückt, die angibt, wohin die Elemente gehen. Sie können den Quellcode für z.B. sorted und map für Beispiele.

    
Louis Wasserman 28.01.2016 18:33
quelle