java - 从文件加载大 HashMap<String, TreeMap> 会给出 java.lang.OutOfMemoryError(超出 GC 开销限制)

标签 java garbage-collection hashmap out-of-memory bigdata

我的问题简而言之:

  • 我有一台机器有 500 GB RAM 没有交换空间(绰绰有余):top 命令显示 500GB 的空闲内存
  • 我有一个一个 20GB 的文件,其中包含三元组(stringOfTypeX、stringOfTypeY、double val)。意思是对于一个 X 类型的字符串,文件平均有 20-30 行,每行包含这个 X 类型的字符串加上一个(不同的)Y 类型的字符串和相关的 double 值
  • 我想在内存索引中加载文件 HashMap < StringOfTypeX, TreeMap < StringOfTypeY, val >>
  • 我使用 BufferedReader.readLine() 编写了一个 Java 程序
  • 在此程序中,hashmap 在构造函数中使用 initCapacity 初始化,该 initCapacity 是 X 类型的不同字符串的预期数量(键的预期数量)的 2 倍
  • 我使用以下方法运行程序:java -jar XXX.jar -Xms500G -Xmx500G -XX:-UseGCOverheadLimit
  • 该程序似乎处理文件行的速度越来越慢:起初,它每分钟处理 2M 行,但随着每 block 2M 行,它变得越来越慢。在 16M 行之后,它几乎停止,最终,它会抛出一个 java.lang.OutOfMemoryError(GC overhead limit exceeded)
  • 在抛出该错误之前,top 命令显示它消耗了 500GB 内存的 6%(并且这个值是常量,程序在其剩余生命周期中不会消耗比这更多的内存)
  • 我已经阅读了与此相关的所有可能的互联网线程。似乎没有任何效果。我猜 GC 开始做很多事情,但我不明白为什么它会这样做,因为我试图在开始之前为 hashmap 分配足够的 RAM。无论如何,无论我给出什么命令行参数,似乎都不能强制 JVM 预先分配大量 RAM。如果这是真的,那么 Xmx 和 Xms 参数的实际用途是什么?

有人有什么想法吗?非常感谢!!

更新:

  • 我的 jvm 是 64 位的
  • 515 GB RAM 的 6.1% 是 ~ 32GB。似乎 JVM 不允许使用超过 32 GB 的空间。正在关注this post我试图使用标志 -XX:-UseCompressedOops 禁用压缩指针的使用。然而,什么都没有改变。限制仍然是 32GB。
  • 在任何时间点都没有进行交换(使用 top 检查)
  • 运行 -Xms400G -Xmx400G 无法解决问题

最佳答案

误诊此类问题相当普遍。

500 GB 应该绰绰有余,假设你有超过 500 GB 的主内存,swap 就不行了。

如果您有字符串,20 GB 的文件可能有显着的扩展比例。例如一个 16 个字符的字符串将使用大约 80 个字节的内存。一个 Double 在 64 位 JVM 中使用大约 24 个字节,而不是您可能期望的 8 个字节。

HashMap 和 TreeMap 每个条目使用大约 24 个额外字节。

使用 readLine() 并将容量加倍就可以了。实际上 expected-size*4/3 就足够了,尽管它总是使用 2 的下一次幂。

设置 -Xms 会预分配特定的内存(或几乎是那个数字,通常会无缘无故地超出 1%)

每分钟 200 万行是相当慢的。这表明您的开销已经非常高。我会寻找接近每秒 100 万行的东西。

与 JVM 的大小相比,1600 万个条目算不了什么。我猜你已经开始交换,你看到的错误是因为 GC 花费的时间太长,而不是因为堆太满。

您有多少空闲主内存?例如在 top 应用程序结束后您会看到什么。

关于java - 从文件加载大 HashMap<String, TreeMap> 会给出 java.lang.OutOfMemoryError(超出 GC 开销限制),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23469111/

相关文章:

java - 在单元测试中去抖忽略超时

python - 覆盖对象实例不释放内存?

Java Hashmap - 多线程放置

java - LinkedHashMap 的内部实现与 HashMap 实现有何不同?

java - 我怎样才能制作以下对象?

java - 如何旋转伸展树(Splay Tree)中的节点?

java - "Unresolved requirement: Import-Package: javax.ws.rs"在 Tomcat 上为 Liferay 部署 OSGi 模块时

java - 单 CPU 机器的最佳 GC 线程数

java - JVM 内存不足

java - 从 HashMap<String, String> 中为字符串的每个字符检索值返回 NULL