我想使用键控流,我想知道哪种方法在高吞吐量下更好 假设我有以下
trait A{
val id: Int
def isFoo: Boolean
}
case class Foo(id: Int) extends A{
override def isFoo = true
}
case class Bar(id: Int) extends A{
override def isFoo = false
}
val as = List[A](Foo, Bar)
val fs: List[Foo] = as.flatMap{
case Foo => Some(Foo)
case _ => None
}
我可以拥有以下视频流
val src: DataStream[A] = env.fromElements(as:_*)
我有这些选择:
src.filter(_.isFoo).keyBy(_.id).map(...more processing...)
src.filter(_.isInstanceOf[Foo]).keyBy(_.id).map(...more processing...)//here we can remove the isFoo method
src.flatMap{
case f:Foo => Some(f)
case _ => None
}.keyBy(_.id).map(...more processing...)
我唯一的理由
选项 3 允许我从id
和特征本身中删除Bar
字段,因为它将创建Foo
的流,这更直接。但是,按字段过滤似乎比 mapping 轻得多,特别是在高吞吐量方面。
你怎么看 ? 答案 0 :(得分:14)
简短的回答:几乎可以肯定,这无关紧要,而且浪费这些时间来担心这些特定的编写过滤操作的最快方式。 ...more processing...
部分几乎肯定会成为您应用程序中的瓶颈,您应该编写最清楚,最容易维护的过滤器版本。
稍微长一点的答案:即使这是某种奇怪的情况,其中这些选项中的一个明显优于其他选项,但实际上会影响应用程序的性能,您最好还是为自己编写基准测试而不是让Stack Overflow上的陌生人推测您的用例。
如果您真的要让Stack Overflow上的一个陌生人推测您的用例,我想说的一件事是,flatMap
-进入Option
可能不是这里的最佳选择,因为它会导致很多不必要的分配。这是一些替代实现的超级快速基准(使用Vector
而不是Flink,因此要花点时间看一下结果)
import org.openjdk.jmh.annotations._
@State(Scope.Thread) class FilterBenchmark {
val values: Vector[A] = (0 to 100).map {
case i if i % 2 == 0 => Foo(i)
case i => Bar(i)
}.toVector
@Benchmark def withIsFoo: Vector[A] = values.filter(_.isFoo)
@Benchmark def withIsInstanceOf: Vector[A] = values.filter(_.isInstanceOf[Foo])
@Benchmark def withFlatMap: Vector[A] = values.flatMap {
case f @ Foo(_) => Some(f)
case _ => None
}
@Benchmark def withFlatMapTypeMatch: Vector[A] = values.flatMap {
case f: Foo => Some(f)
case _ => None
}
@Benchmark def withCollect: Vector[A] = values.collect {
case f @ Foo(_) => f
}
@Benchmark def withCollectTypeMatch: Vector[A] = values.collect {
case f: Foo => f
}
}
还有一些结果(关于2.12.8):
Benchmark Mode Cnt Score Error Units
FilterBenchmark.withCollect thrpt 10 1359035.689 ± 2749.815 ops/s
FilterBenchmark.withCollectTypeMatch thrpt 10 1361227.743 ± 2337.850 ops/s
FilterBenchmark.withFlatMap thrpt 10 113074.826 ± 288.107 ops/s
FilterBenchmark.withFlatMapTypeMatch thrpt 10 113188.419 ± 262.826 ops/s
FilterBenchmark.withIsFoo thrpt 10 1254404.326 ± 3997.759 ops/s
FilterBenchmark.withIsInstanceOf thrpt 10 1257725.670 ± 6115.773 ops/s
这个故事的寓意(在我看来)是flatMap
偏离了一个数量级,而且显然很糟糕,但是其他选择之间没有足够的差异来使绩效与决策相关。