pekko/akka-stream/src/main/scala/akka/stream/Fusing.scala
Roland Kuhn b255a19374 simplify materialized value computation tree, fixes #20015
- also fixes materialized value sources for graphs that import zero or
  one graphs, with and without Fusing
2016-03-16 17:05:46 +01:00

68 lines
3.1 KiB
Scala
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package akka.stream
import scala.collection.immutable
import akka.stream.impl.StreamLayout._
import akka.stream.impl.fusing.{ Fusing Impl }
import scala.annotation.unchecked.uncheckedVariance
/**
* This class holds some graph transformation functions that can fuse together
* multiple operation stages into synchronous execution islands. The purpose is
* to reduce the number of Actors that are created in order to execute the stream
* and thereby improve start-up cost as well as reduce element traversal latency
* for large graphs. Fusing itself is a time-consuming operation, meaning that
* usually it is best to cache the result of this computation and reuse it instead
* of fusing the same graph many times.
*
* Fusing together all operations which allow this treatment will reduce the
* parallelism that is available in the stream graphs execution—in the worst case
* it will become single-threaded and not benefit from multiple CPU cores at all.
* Where parallelism is required, the [[akka.stream.Attributes#AsyncBoundary]]
* attribute can be used to declare subgraph boundaries across which the graph
* shall not be fused.
*/
object Fusing {
/**
* Fuse all operations where this is technically possible (i.e. all
* implementations based on [[akka.stream.stage.GraphStage]]) and not forbidden
* via [[akka.stream.Attributes#AsyncBoundary]].
*/
def aggressive[S <: Shape, M](g: Graph[S, M]): FusedGraph[S, M] = Impl.aggressive(g)
/**
* A fused graph of the right shape, containing a [[FusedModule]] which
* holds more information on the operation structure of the contained stream
* topology for convenient graph traversal.
*/
case class FusedGraph[+S <: Shape @uncheckedVariance, +M](override val module: FusedModule,
override val shape: S) extends Graph[S, M] {
// the @uncheckedVariance look like a compiler bug ... why does it work in Graph but not here?
override def withAttributes(attr: Attributes) = copy(module = module.withAttributes(attr))
}
object FusedGraph {
def unapply[S <: Shape, M](g: Graph[S, M]): Option[(FusedModule, S)] =
g.module match {
case f: FusedModule => Some((f, g.shape))
case _ => None
}
}
/**
* When fusing a [[Graph]] a part of the internal stage wirings are hidden within
* [[akka.stream.impl.fusing.GraphInterpreter#GraphAssembly]] objects that are
* optimized for high-speed execution. This structural information bundle contains
* the wirings in a more accessible form, allowing traversal from port to upstream
* or downstream port and from there to the owning module (or graph vertex).
*/
final case class StructuralInfo(upstreams: immutable.Map[InPort, OutPort],
downstreams: immutable.Map[OutPort, InPort],
inOwners: immutable.Map[InPort, Module],
outOwners: immutable.Map[OutPort, Module],
allModules: Set[Module])
}