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

Posted

技术标签:

【中文标题】使用大型数据结构时,避免 Java(eclipse) 中的“内存不足错误”?【英文标题】:Avoid an "out of memory error" in Java(eclipse), when using large data structure? 【发布时间】:2011-01-28 10:24:25 【问题描述】:

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

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

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

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

我做过的事情包括:

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

我相当有信心这不会是一个简单的代码行解决方案,但很可能需要一种非常新的方法。我正在寻找这种方法是什么,有什么想法吗?

谢谢, B.

【问题讨论】:

请注意,使用这些参数启动 Eclipse 不会有帮助,除非您的代码是 Eclipse 插件。如果你只是使用 Eclipse 作为 IDE,那么你需要更改应用程序的运行配置,而不是 Eclipse 的启动。 啊,谢谢约阿希姆。我没有单独运行它,它仍然给我同样的错误(虽然需要更长的时间才能到达那里,我想这是一个改进) 【参考方案1】:

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

【讨论】:

【参考方案2】:

内存不足问题有多种原因。

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

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

然而最终你会遇到一个十字路口,你必须在虚拟化分区之间做出选择。

虚拟化在这种情况下仅仅意味着某种形式的假装内存比实际内存多。操作系统将其与虚拟地址空间一起使用,并将硬盘空间用作额外内存。这可能意味着一次只将部分数据结构保存在内存中,而将其余数据结构持久化到辅助存储(例如文件或数据库)。

分区将您的数据拆分到多个服务器(无论是真实的还是虚拟的)。例如,如果您在 NASDAQ 跟踪股票交易,您可以在 server1 上放置以“A”开头的股票代码,在 server2 上放置以“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

这只是一个想法。再一次,在不知道细节的情况下很难评论。

【讨论】:

你已经提到了我已经尝试过的几乎所有东西,正如我在我的帖子中提到的(我承认它的细节很少)。您的后一种解决方案解决了我的问题,但我不想做任何太复杂的事情(分区声音超出了我的范围)。【参考方案3】:

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

如果你真的那么多条目(你当前的数组在某处over 3 gigabytes already,即使假设没有开销),那么你将不得不使用某种磁盘存储,或者延迟加载/卸载系统。

【讨论】:

+1 听起来 OP 正试图创建一个幼稚的索引。尽管每个文本可能有 30k 个单词的词汇表,但该矩阵中会有大量的零。 是的——我想到了一个稀疏数组,但如果没有更多关于数据结构意图的细节,除了推测之外,它很难做。 我喜欢这个声音,我会试一试。 @msw,你很接近,它类似于concordance(而且非常天真;)。这是一种不同的统计分析方法,称为超空间类比语言 (HAL)。 到目前为止这对我有用。现在我只需要让它运行得更快。【参考方案4】:

如果您不需要为 2D 数组中的每个值提供完整的 32 位(整数大小),也许更小的类型(例如字节)可以解决问题?此外,您应该给它尽可能多的堆空间——对于现代系统来说,2GB 仍然相对较小。 RAM 很便宜,尤其是当您希望在内存中进行大量处理时。

【讨论】:

以上是关于使用大型数据结构时,避免 Java(eclipse) 中的“内存不足错误”?的主要内容,如果未能解决你的问题,请参考以下文章

优化导入时如何避免重新排序

使用大型数据库时,如何避免 UITableView 中的自定义单元格加载时间过长

JAVA使用Eclipse依赖生成jar包时,避免最外层同时生成资源文件的配置。

Eclipse启动时,项目文件丢失了,这种问题如何避免?

JAVA读写文件,如何避免中文乱码

在 R 中处理大型 csv 文件时避免挂断