=str #19299 Performance Flow.flatMapMerge

This commit is contained in:
Alexander Golubev 2016-02-02 16:39:47 -05:00
parent ad8ab128c4
commit b2b2ce44b5
19 changed files with 224 additions and 134 deletions

View file

@ -4,13 +4,13 @@
package akka.stream.impl.fusing
import java.util.Arrays
import akka.actor.ActorRef
import akka.event.LoggingAdapter
import akka.stream.stage._
import scala.annotation.tailrec
import scala.collection.immutable
import akka.stream._
import akka.stream.impl.StreamLayout._
import akka.stream.impl.fusing.GraphStages.MaterializedValueSource
import scala.concurrent.forkjoin.ThreadLocalRandom
import scala.util.control.NonFatal
import java.{ util ju }
@ -193,12 +193,12 @@ private[akka] object GraphInterpreter {
override def toString: String =
"GraphAssembly\n " +
stages.mkString("[", ",", "]") + "\n " +
originalAttributes.mkString("[", ",", "]") + "\n " +
ins.mkString("[", ",", "]") + "\n " +
inOwners.mkString("[", ",", "]") + "\n " +
outs.mkString("[", ",", "]") + "\n " +
outOwners.mkString("[", ",", "]")
stages.mkString("Stages: [", ",", "]") + "\n " +
originalAttributes.mkString("Attributes: [", ",", "]") + "\n " +
ins.mkString("Inlets: [", ",", "]") + "\n " +
inOwners.mkString("InOwners: [", ",", "]") + "\n " +
outs.mkString("Outlets: [", ",", "]") + "\n " +
outOwners.mkString("OutOwners: [", ",", "]")
}
object GraphAssembly {
@ -348,7 +348,8 @@ private[stream] final class GraphInterpreter(
val outHandlers: Array[OutHandler], // Lookup table for the outHandler of the connection
val logics: Array[GraphStageLogic], // Array of stage logics
val onAsyncInput: (GraphStageLogic, Any, (Any) Unit) Unit,
val fuzzingMode: Boolean) {
val fuzzingMode: Boolean,
val context: ActorRef) {
import GraphInterpreter._
// Maintains additional information for events, basically elements in-flight, or failure.
@ -523,13 +524,13 @@ private[stream] final class GraphInterpreter(
* Executes pending events until the given limit is met. If there were remaining events, isSuspended will return
* true.
*/
def execute(eventLimit: Int): Unit = {
def execute(eventLimit: Int): Int = {
if (Debug) println(s"$Name ---------------- EXECUTE $queueStatus (running=$runningStages, shutdown=$shutdownCounters)")
val currentInterpreterHolder = _currentInterpreter.get()
val previousInterpreter = currentInterpreterHolder(0)
currentInterpreterHolder(0) = this
var eventsRemaining = eventLimit
try {
var eventsRemaining = eventLimit
while (eventsRemaining > 0 && queueTail != queueHead) {
val connection = dequeue()
try processEvent(connection)
@ -551,6 +552,7 @@ private[stream] final class GraphInterpreter(
}
if (Debug) println(s"$Name ---------------- $queueStatus (running=$runningStages, shutdown=$shutdownCounters)")
// TODO: deadlock detection
eventsRemaining
}
def runAsyncInput(logic: GraphStageLogic, evt: Any, handler: (Any) Unit): Unit =
@ -654,7 +656,7 @@ private[stream] final class GraphInterpreter(
finalizeStage(logic)
}
// Returns true if the given stage is alredy completed
// Returns true if the given stage is already completed
def isStageCompleted(stage: GraphStageLogic): Boolean = stage != null && shutdownCounter(stage.stageId) == 0
// Register that a connection in which the given stage participated has been completed and therefore the stage
@ -734,12 +736,13 @@ private[stream] final class GraphInterpreter(
* Only invoke this after the interpreter completely settled, otherwise the results might be off. This is a very
* simplistic tool, make sure you are understanding what you are doing and then it will serve you well.
*/
def dumpWaits(): Unit = {
println("digraph waits {")
def dumpWaits(): Unit = println(toString)
for (i assembly.stages.indices) {
println(s"""N$i [label="${assembly.stages(i)}"]""")
}
override def toString: String = {
val builder = new StringBuilder("digraph waits {\n")
for (i assembly.stages.indices)
builder.append(s"""N$i [label="${assembly.stages(i)}"]""" + "\n")
def nameIn(port: Int): String = {
val owner = assembly.inOwners(port)
@ -756,17 +759,18 @@ private[stream] final class GraphInterpreter(
for (i portStates.indices) {
portStates(i) match {
case InReady
println(s""" ${nameIn(i)} -> ${nameOut(i)} [label="shouldPull"; color=blue]; """)
builder.append(s""" ${nameIn(i)} -> ${nameOut(i)} [label=shouldPull; color=blue]""")
case OutReady
println(s""" ${nameOut(i)} -> ${nameIn(i)} [label="shouldPush"; color=red]; """)
builder.append(s""" ${nameOut(i)} -> ${nameIn(i)} [label=shouldPush; color=red];""")
case x if (x | InClosed | OutClosed) == (InClosed | OutClosed)
println(s""" ${nameIn(i)} -> ${nameOut(i)} [style=dotted; label="closed" dir=both]; """)
builder.append(s""" ${nameIn(i)} -> ${nameOut(i)} [style=dotted; label=closed dir=both];""")
case _
}
builder.append("\n")
}
println("}")
println(s"// $queueStatus (running=$runningStages, shutdown=${shutdownCounter.mkString(",")})")
builder.append("}\n")
builder.append(s"// $queueStatus (running=$runningStages, shutdown=${shutdownCounter.mkString(",")})")
builder.toString()
}
}