加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

为什么Scala hashmap慢?

发布时间:2020-12-16 09:41:42 所属栏目:安全 来源:网络整理
导读:可以做些什么呢? 我已经运行了一些测试,似乎Scala Hashmap比Java HashMap慢得多。请证明我错了! 对我来说,Hashmap的全部要点是从一个给定的键快速访问一个值。所以当速度很重要时,我发现自己正在使用Java 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
Long(60),Java(93),Open(170),MutableSc(243),ImmutableSc(317)

case对象键,n = 20
Java(195),AnyRef(230)

解决方法

首先:使用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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读