从java到scala集合的隐式转换成本
我想知道从java集合到scala集合的隐式转换的成本。在中,有几种隐式双向转换,据说“从源类型转换为目标类型,然后再转换回来将返回原始源对象” 我的结论是,成本应该很低(包装),但还是多少钱 我问这个问题是因为我在一些scala代码中使用java集,在导入从java到scala集合的隐式转换成本,java,scala,performance,collections,type-conversion,Java,Scala,Performance,Collections,Type Conversion,我想知道从java集合到scala集合的隐式转换的成本。在中,有几种隐式双向转换,据说“从源类型转换为目标类型,然后再转换回来将返回原始源对象” 我的结论是,成本应该很低(包装),但还是多少钱 我问这个问题是因为我在一些scala代码中使用java集,在导入asScalaSet时,java集被隐式转换为scala集(在某些地方我确实需要它)。但是,对于非常少的访问器,例如size() 有人知道吗?我决定从实际的角度回答你的问题。我使用以下简单的JMH基准测试原始scala集合和转换的scala集
asScalaSet
时,java集被隐式转换为scala集(在某些地方我确实需要它)。但是,对于非常少的访问器,例如size()
有人知道吗?我决定从实际的角度回答你的问题。我使用以下简单的JMH基准测试原始scala集合和转换的scala集合(使用隐式转换)每秒的操作 请查看以下基准代码:
import org.openjdk.jmh.annotations._
import scala.collection.JavaConversions._
@State(Scope.Thread)
class WrapperBenchmark {
val unwrappedCollection = (1 to 100).toSet
val wrappedCollection: java.util.Set[Int] = (1 to 100).toSet[Int]
@Benchmark
def measureUnwrapped: Int = unwrappedCollection.size
@Benchmark
def measureWrapped: Int = wrappedCollection.size()
}
我使用sbt和sbt jmh插件来运行。请查看以下结果:
[info] Benchmark Mode Cnt Score Error Units
[info] WrapperBenchmark.measureUnwrapped thrpt 200 353214968.844 ± 1534779.932 ops/s
[info] WrapperBenchmark.measureWrapped thrpt 200 284669396.241 ± 4223983.126 ops/s
因此,基本上根据结果,确实存在开销。我将继续我的研究,并在稍后的问题更新中说明原因
如果您希望我为您的未来研究分享完整的sbt项目,请告诉我。以下是使用Scala 2.13.1的jmh基准测试结果 其中
sbt“jmh:run-i10-wi5-f2-t1试验台。So31830028”
[info] Benchmark Mode Cnt Score Error Units
[info] So31830028.java thrpt 20 356515729.840 ± 64691657.672 ops/s
[info] So31830028.javaAsScala thrpt 20 270053471.338 ± 36854051.611 ops/s
[info] So31830028.scala thrpt 20 448415156.726 ± 53674976.259 ops/s
[info] So31830028.scalaAsJava thrpt 20 211808793.234 ± 57898858.737 ops/s
确实,这似乎是一个相当大的成本。我不知道编译器有多聪明,但在很多情况下,它似乎应该能够避免分配包装类、内联调用(如
size
),并且不会产生任何开销?这不是对你的问题的回答,而是通常的“魔力”JavaConversion有点不受欢迎,而倾向于更显式的转换,这需要您编写.asScala或.asJava来实现显式转换。Good info@RüdigerKlaehn。这确实很有用,这样至少我可以控制转换发生的时间。来自python的背景,我只能同意这一点(“显式优于隐式”-python的禅宗)对于鱼和鱼竿的Tx:-)我现在不会再深入研究它,但你给了我工具来回答我可能遇到的类似问题。请随意分享这样一个sbt项目,以对简单功能进行基准测试。您的基准测试功能创建了集合,因此您对[create+wrapping]进行基准测试,显然,创建要比wrapping长得多。您能在之前创建一次初始集吗:classso318{val set=(1到1000000)。toSet;val javaSet=set.asJava;def scala=set.size;def scalaAsJava=javaSet.size}
。另外,请注意,我的问题是关于另一种方式:在java集上使用scala包装器的成本,而不是直接在java集上使用。@Juh_u确实您是对的。谢谢你指出错误!请参阅编辑后的答案以获取更新结果。
[info] Benchmark Mode Cnt Score Error Units
[info] So31830028.java thrpt 20 356515729.840 ± 64691657.672 ops/s
[info] So31830028.javaAsScala thrpt 20 270053471.338 ± 36854051.611 ops/s
[info] So31830028.scala thrpt 20 448415156.726 ± 53674976.259 ops/s
[info] So31830028.scalaAsJava thrpt 20 211808793.234 ± 57898858.737 ops/s