2014-09-04 77 views
1

我们的Java程序具有树形结构大对象,ArrayList和MultiMaps。Java大型对象存储 - 协议缓冲区,MemoryMappedFiles

我遇到的问题是,我们已经分配了3GB的堆内存,但它仍然没有空间。

我想知道如果在这里任何人都可以提出一个方法来存储外堆这些对象和读取数据的块放回每个处理的呼叫需要的基础上java程序。我有兴趣将它们存储在文件中而不是其他原因的数据库中。

我碰到了“内存映射文件”,有些人建议“协议缓冲区”上一个相关的问题,这些都是目前外星人的概念给我,想知道如果有一个简单的方法。我也无法在这两个概念上找到好的例子。

真的很感谢你对此的帮助。

性能是非常重要的考虑因素,我知道JVM堆分配,但我不寻找增加的JVM堆大小。

+0

听起来像一个* XY问题*。认为我错了?提供有关“大型对象”的详细信息以及如何使用它们。告诉我们为什么你想探索像mem映射文件这样的奇特解决方案。 – Andreas 2014-09-04 19:34:15

+0

我已经把数据放在一个带有Java的内存映射文件中,但缺点是那里存储的数据不是Java对象 - 它看起来像一个大字节数组。 – antlersoft 2014-09-04 19:35:08

+0

@Andreas,谢谢你的回应。我们将后端表数据读入Java,并基于某些逻辑将此数据转换为Java数据结构 - 树数据结构,对象ArrayList和MultiMaps。 我有Java逻辑从这些对象和数据结构读取并根据它们的输入处理用户请求。 如果仍然不清楚,我真的很抱歉。希望我能提供更多细节。 而我不得不寻求奇特的解决方案。我会采纳你的任何建议。 – 2014-09-04 19:45:00

回答

1

您可能会考虑将数据存储在Chronicle Map之类的东西中。这使用堆内存,并可以存储和访问,而不会产生任何垃圾。这可以让你减少堆的大小,但你仍然需要购买一块合理的内存。我建议你考虑至少有32 GB的内存,不管你是在堆上使用还是在堆外使用大型数据集。

没有理由我必须去异国情调的解决方案

在这种情况下,坚持一个上堆的解决方案。你可以购买大约200美元的16 GB内存。

我不是在寻找增加JVM堆大小。

问问你自己愿意投入多少时间/金钱以避免增加堆。你当然可以做到这一点,但为了节省4 GB,我不会在这一天度过一天。节省40 GB或400 GB或4 TB是另一回事。

+0

嗨,彼得, 非常感谢您的回复。 我会检查你的建议。 而且,这不是我个人的工作,我可以轻松获得16GB的RAM。这是我的办公室项目,想要获得这么多的记忆并不容易,相信我。 – 2014-09-04 20:32:56

+2

@bluzeee是的,有些地方会很乐意浪费大量时间/金钱以避免在硬件上花费金钱。 – 2014-09-04 20:49:50

0

您可能能够使用Guava中的不可变集合,它们通常会减少内存消耗。

您可以使用String.intern如果字符串把你的记忆中相当一部分。

您可以保存使用trove4j如果你有很多盒装原语很多。

你可以做一些小技巧,例如使用更小的数据类型,等等....

但你真的应该浪费具有尽可能多的RAM作为智能手机电脑的时间在你的办公室获取更多的内存!

+0

感谢您的回复。 我检查过Trove和HPPC,但我有对象而不是原始图片。我也检查了巨大的集合,并根据我检查了什么,我需要自定义接口,但我使用了ArrayList和收集对象(不是单独的字符串)的映射,它们是内存的主要消费者。 我终于落户Fastutil,但没有看到任何内存节省,不知道如果我做错了什么。我必须进一步检查。 – 2014-09-07 03:15:49

1

Protocol Buffers的不内存映射文件很好地工作,因为该文件中包含的编码数据,必须首先被解码,然后才能使用它。该解码步骤会生成堆对象。如果将文件拆分成许多小型消息,并在需要时按需解码,但可以立即丢弃解码版本,则可以将Protobufs与内存映射文件一起使用。但是,如果您不小心,可能会浪费大量时间重复解码相同的数据。

Cap'n Proto是一种较新的格式,它与协议缓冲区非常相似,但明确设计用于处理内存映射文件。磁盘格式的设计使得它可以在没有解码步骤的情况下就地使用。我们正在研制一种Java version,该产品应在几周内准备好用于生产。

(披露:我是头儿原的创造者,也是以前Protocol Buffers的在谷歌的维护者)

+0

感谢您的回复。 – 2014-09-07 03:09:26