【问题标题】:scala HashSet[String].contains slows down app dramaticallyscala HashSet[String].contains 显着降低应用程序的速度
【发布时间】:2015-02-26 14:26:18
【问题描述】:

我有一个类似 ETL 的小型应用程序,它从多个来源获取一些数据,通过一些 API 规则将它们组合起来,最后将它们吐出到目标文件中。

这些项目具有计算出的唯一 ID 字符串,并且由于多个源和 API 规则的混合,可能会发生两次或更多次生成相同的目标对象。听起来很奇怪,但细节很有意义。不幸的是,我在导出之前无法检测到这一点。

为了让每个唯一 ID 对象只导出一次,我认为我可以只存储它们的 ID 并通过以下方式进行比较:

private val Ids = new mutable.HashSet[String]
def write(entity:Entity) {
  val eID = entity.id.intern
  Ids.synchronized { // i somethimes use .par.map and call write()
    if(Ids.contains(eID)) {
      return
    }

    Ids += eID
  }
  .. process

现在这在一段时间内可以正常工作,但在该哈希集中有大约 50.000.000 个元素,它会大大减慢整个过程。

我以 32Gig 的字符串重复数据删除、xmx/xms 启动应用程序。它只使用大约 9 Gig max,所以不知道是什么导致了速度变慢。我将 StringTableSize 设置为天文尺寸以及高大的尺寸,没有明显的变化。

我的想法是在一般情况下比较坏吗?还是哈希集的选择?有什么建议可以调试吗?香蕉?

如果我注释掉 Ids.contains 和 += 行,我的应用程序大约需要 17 分钟。使用 id 比较启用了几个小时。

有什么想法/线索/建议吗?

我的总体比较不好的想法吗? 还是哈希集的选择? 有什么建议/如何调试?使用 VisualVM,我只花费了大约 60% 的时间在包含方法上。

可能可以花这么长时间,因为对于每个第 n 个元素,我有 n-1 个比较..?

提前致谢。

Scala 2.11.5

【问题讨论】:

    标签: performance scala hashmap contains


    【解决方案1】:

    我不确定这是否与 scala HashSet 有关。罪魁祸首是 String#intern 方法,它存在一些严重的性能问题。见Performance penalty of String.intern()

    如果您希望通过实习确保可以在工作集中进行计算,则必须编写自己的实习表。编写一个好的高性能实习生表可能非常棘手。所以如果你能负担得起对 guava 的依赖,请使用 Guava Cache。

    你试过完全放弃实习吗?

    【讨论】:

    • 嘿。是的,实习生是一种昂贵的尝试来加快速度。实际上,我在这里使用 .intern 时甚至都没有注意到损失或收益。老实说,这是一种非常愚蠢的绝望行为;)
    猜你喜欢
    • 2017-10-13
    • 1970-01-01
    • 2018-06-18
    • 2022-10-19
    • 2012-10-24
    • 1970-01-01
    • 2012-09-09
    • 2022-08-06
    • 2019-05-03
    相关资源
    最近更新 更多