【发布时间】:2012-10-31 20:55:41
【问题描述】:
我试图找出 Scala 的散列函数对大型散列表(具有数十亿个条目,例如存储特定 DNA 出现的频率)的扩展程度。
然而,有趣的是,HashMap 和 OpenHashMap 似乎都忽略了指定初始大小的参数(2.9.2. 和 2.10.0,最新版本)。
我认为之所以如此,是因为在前 800.000 左右之后添加新元素会变得慢得多。
我尝试增加要插入的字符串中的熵(只有下面代码中的字符 ACGT),但没有效果。
对这个具体问题有什么建议吗?我也很高兴听到您对使用 Scala 的内置类型对于具有数十亿个条目的哈希表是否是一个好主意的意见。
import scala.collection.mutable.{ HashMap, OpenHashMap }
import scala.util.Random
object HelloWorld {
def main(args: Array[String]) {
val h = new collection.mutable.HashMap[String, Int] {
override def initialSize = 8388608
}
// val h = new scala.collection.mutable.OpenHashMap[Int,Int](8388608);
for (i <- 0 until 10000000) {
val kMer = genkMer()
if(! h.contains(kMer))
{
h(kMer) = 0;
}
h(kMer) = h(kMer) + 1;
if(i % 100000 == 0)
{
println(h.size);
}
}
println("Exit. Hashmap size:\n");
println(h.size);
}
def genkMer() : String =
{
val nucs = "A" :: "C" :: "G" :: "T" :: Nil
var s:String = "";
val r = new scala.util.Random
val nums = for(i <- 1 to 55 toList) yield r.nextInt(4)
for (i <- 0 until 55) {
s = s + nucs(nums(i))
}
s
}
}
【问题讨论】:
-
你不会内存不足吗?
-
32 位还是 64 位 jvm?关于忽略初始大小:没有,你可以查看HashMap的源代码
-
感谢您的回答。澄清一下,这将部署在具有 256G+ RAM 的机器上。 @Noah:但是每次翻倍后它都必须复制存储桶内容,对吗?但即使这是真的,它也无法向我解释为什么这种性能下降会发生在 800.000 次左右的迭代之后——我预计在进行重新排列时会急剧下降,然后再恢复到全速。
-
@Arjan:64 位。除了我描述的性能下降之外,无论我设置什么初始大小,我的程序的内存占用都不会改变。
-
在下面查看我的更新,你需要增加你的最大 heep size。