在使用大型数据结构时,避免Java(eclipse)中出现“内存不足错误”?

时间:2010-03-17 04:55:41

标签: java eclipse large-data-volumes heap-memory out-of-memory

好的,所以我正在编写一个程序,不幸的是需要使用庞大的数据结构来完成它的工作,但它在初始化期间失败并出现“内存不足错误”。虽然我完全理解这意味着什么以及为什么它是一个问题,但我很难克服它,因为我的程序需要使用这个大型结构,我不知道任何其他方式来存储它。

该程序首先索引我提供的大量文本文件。这很好。

然后它使用此索引初始化大型2D数组。该数组将具有n²个条目,其中“n”是文本语料库中唯一字的数量。对于相对较小的块我正在测试它(大约60个文件)它需要制作大约30,000x30,000个条目。一旦我在我的完整预期语料库上运行它,这可能会更大。

它在索引之后每次都会失败,同时它正在初始化数据结构(稍后要处理)。

我所做的事情包括:

  • 修改我的代码以使用原始int[]而不是TreeMap
  • 消除冗余结构等......
  • 此外,我已使用-Xmx2g运行程序以最大化我分配的内存

我相信这不是一个简单的代码解决方案,但很可能需要一种非常新的方法。我正在寻找那种方法,任何想法?

谢谢, 乙

4 个答案:

答案 0 :(得分:2)

听起来(对您使用数组的内容做了一些假设)大多数条目都是0.如果是这样,您可以考虑使用sparse matrix表示。

如果您真的拥有那么多条目(您当前的数组位于over 3 gigabytes already,即使没有开销),那么您将不得不使用某种磁盘存储,或者是一个懒惰的加载/卸载系统。

答案 1 :(得分:2)

导致内存不足的原因有多种。

首先,最简单的情况是你只需要更多的堆。当程序可以使用2G正常运行时,您正在使用512M最大堆。增加是-Xmx2048m作为JVM选项,你没事。另外请注意,64位虚拟机将使用高达32位虚拟机内存的两倍,具体取决于该数据的组成。

如果您的问题不那么简单,那么您可以查看优化。用基元替换对象等。这可能是一种选择。根据您发布的内容,我无法说出来。

然而,最终你走到了一条十字路口,你必须在 virtulization partitioning 之间做出选择。

在这种情况下,

虚拟化只是意味着某种形式的假装存在的内存比现有的多。操作系统将此与虚拟地址空间一起使用,并将硬盘空间用作额外内存。这可能意味着一次只将一些数据结构保留在内存中,并将其余数据结构保存到二级存储(例如文件或数据库)。

分区将您的数据拆分到多个服务器(实际或虚拟)。例如,如果您在纳斯达克上跟踪股票交易,您可以在服务器1上放置以“A”开头的股票代码,在服务器2上放置“B”等等。您需要找到一种合理的方法来分割数据,以便减少或者不需要交叉通信,因为交叉通信会限制您的可扩展性。

如此简单的情况,如果你要存储的是30K字和30K x 30K字组合,你可以把它分成四个服务器:

  • A-M x A-M
  • A-M x N-Z
  • N-Z x A-M
  • N-Z x N-Z

这只是一个想法。在不了解具体细节的情况下,这也很难实现。

答案 2 :(得分:1)

这是处理大型数据集的常见问题。您可以根据需要进行优化,但内存永远不够(可能),一旦数据集增长一点,您仍然会被吸烟。最具扩展性的解决方案是简单地减少内存,处理块,并将结构保留在磁盘(数据库/文件)上。

答案 3 :(得分:0)

如果你不需要为2D数组中的每个值提供完整的32位(整数大小),那么像字节这样的较小类型可能会起作用吗?另外,你应该给它尽可能多的堆空间 - 对于现代系统,2GB仍然相对较小。 RAM很便宜,特别是如果你期望在内存中进行大量处理。