为什么Scala hashmap慢?
可以做些什么呢?
我已经运行了一些测试,似乎Scala Hashmap比Java HashMap慢得多。请证明我错了! 对我来说,Hashmap的全部要点是从一个给定的键快速访问一个值。所以当速度很重要时,我发现自己正在使用Java HashMap,这有点难过。我没有足够的经验可以肯定地说,但似乎你混合Java和Scala越多,你可能面临的问题越多。 test("that scala hashmap is slower than java") { val javaMap = new util.HashMap[Int,Int](){ for (i <- 1 to 20) put(i,i+1) } import collection.JavaConverters._ val scalaMap = javaMap.asScala.toMap // check is a scala hashmap assert(scalaMap.getClass.getSuperclass === classOf[scala.collection.immutable.HashMap[Int,Int]]) def slow = { val start = System.nanoTime() for (i <- 1 to 1000) { for (i <- 1 to 20) { scalaMap(i) } } System.nanoTime() - start } def fast = { val start = System.nanoTime() for (i <- 1 to 1000) { for (i <- 1 to 20) { javaMap.get(i) } } System.nanoTime() - start } val elapses: IndexedSeq[(Long,Long)] = { (1 to 1000).map({_ => (slow,fast)}) } var elapsedSlow = 0L var elapsedFast = 0L for ((eSlow,eFast) <- elapses) { elapsedSlow += eSlow elapsedFast += eFast } assert(elapsedSlow > elapsedFast) val fraction : Double = elapsedFast.toDouble/elapsedSlow println(s"slower by factor of: $fraction") } 我错过了什么吗? 答案总结 到目前为止,当将Java 8与Scala 2.11进行比较时,除了LongMap(如果您的键是Ints / Longs),Java HashMap似乎比Scala提供的查询速度更快(对于少量的键)。 性能差异不是很大,在大多数用例中应该是重要的。希望Scala将提高其地图的速度。同时,如果需要性能(使用非整数键)使用Java。 Int键,n = 20 case对象键,n = 20 解决方法
首先:使用nanoTime执行JVM基准测试非常容易出错。使用微型基准框架,如
Thyme,
Caliper或
JMH
第二:您将可变Java散列图与不可变的散文散列图进行比较。不可变的集合可以非常快,但有些情况下,它们永远不会像可变数据结构一样快。 这是一个适用的microbenchmark的可变Java散列图与不可变的scala哈希映射:https://gist.github.com/rklaehn/26c277b2b5666ec4b372 正如你所看到的,scala immutable map比java的可变地图快一点。请注意,一旦您进入较大的地图,情况就不会如此,因为不可变数据结构必须做出一些妥协才能启用structural sharing.我猜测,在这两种情况下,主要的性能问题是将ints整合为整数。 更新:如果您真的想要一个可变的散列,以int为关键字,则scala集合库的正确选择为scala.collection.mutable.LongMap.它使用长的关键字,并且具有比通用Map更好的性能,因为它不必将值。看到要点的结果。 更新2:如果你的键从AnyRef(例如String)延伸,你最好的打赌高性能可变地图是scala.collection.mutable.AnyRefMap (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |